自定义构造函数Haskell上的模式匹配

时间:2017-12-29 02:03:59

标签: haskell types constructor functional-programming pattern-matching

我的自定义类型是:

var result;
var sphereG = new THREE.SphereGeometry( 115, 45, 45 );
var sphereM = new THREE.MeshPhongMaterial({color:"#fff"} );
var sphere = new THREE.Mesh(sphereG,sphereM);
var polyhedronG = new THREE.Geometry();
polyhedronG.vertices.push(
    new THREE.Vector3(-200,200,-200),   //A 0
    new THREE.Vector3(-200,-200,200),   //B 1
    new THREE.Vector3(200,-200,-200),   //D 2
    new THREE.Vector3(-1,-1,-1)         //O 3
);
polyhedronG.faces.push( 
   new THREE.Face3( 0, 1, 2 ),
   new THREE.Face3( 0, 2, 3 ),
   new THREE.Face3( 0, 3, 1 ),
   new THREE.Face3( 3, 2, 1 )
);
var polyhedronM = new THREE.MeshPhongMaterial( {
    color:"#E8FBFF",
    side:THREE.DoubleSide,
    transparent:true,
    opacity:0.1
});
var polyhedron  = new THREE.Mesh(polyhedronG,polyhedronM);
var boxBSP = new ThreeBSP(polyhedron);
var sphereBSP = new ThreeBSP(sphere);
var resultBSP = sphereBSP.subtract(boxBSP);              
result = resultBSP.toMesh();
result.material=new THREE.MeshPhongMaterial({color:'#fff'});

我需要写一个函数

data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq)

实施例

foo :: Eq a => a -> Tree a -> [Tree a]

我的代码如下(使用模式匹配)

foo 3 (Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3])

-- this should print [Node [leaf 5, leaf 3, leaf 6], leaf 6, leaf 44] i.e - all elements that follow a "Leaf 3" in the Tree

但是我收到错误:

foo n (Leaf _) = []

foo n (Node (Node z):y:xs) = if length (Node z):y:xs < 2 then [] 
                else (foo n (Node z)):(foo n y:xs)

foo n (Node (Leaf z):y:xs) = if length (Leaf z):y:xs < 2 then [] 
                else if Leaf n == Leaf z then [y]:(foo n y:xs)
                else (foo n y:xs)

但模式• Couldn't match expected type ‘Tree a’ with actual type ‘[Tree a]’ • In the pattern: Node (Node z) : y : xs 可以代表输入

Node (Node z) : y : xs

我说错了吗?这对我来说似乎很完美。

为什么模式匹配失败?

1 个答案:

答案 0 :(得分:1)

我在repl.it上设置了一个示例,但代码如下。

我做的第一件事是为函数添加一个更具体的签名,以便更容易推理。一旦您完成了所有工作,请随意将其更改回原点签名。与其他方式相比,从具体到抽象更容易。

  • 第一个问题是模式中缺少括号(这意味着您尝试与Tree a匹配而不是[Tree a]。原始(Node (Node z):y:xs)评估如下:{ {1}}。为了方便起见,我在下面的模式中添加了((Node (Node z)):y:xs) ,但您可以替换它,这不是必需的。
  • 第二个问题是你真的试图将all@堵塞到[Tree a],因为Tree ay:xs中意味着什么,所以我将其替换为foo n y:xs Node (y:xs)
  • 第三个问题是Tree a的模式匹配并非详尽无遗,最后添加了一个包罗万象,你想要考虑你的预期行为并清理它。

代码如下:

foo

输出:

module Main where

data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq)

foo :: Int -> Tree Int -> [Tree Int]
foo n (Leaf _) = []

foo n (Node all@((Node z):xs)) = if length all < 2 then [] 
            else (foo n (Node z)) ++ (foo n (Node xs) )

foo n (Node all@((Leaf z):y:xs)) = if length all < 2 then [] 
            else if Leaf n == Leaf z then [y] ++ (foo n (Node (y:xs)))
            else (foo n (Node (y:xs)))
foo _ _ = []

myTree :: Tree Int
myTree = Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3]


main :: IO ()
main = do
  print (foo 3 myTree)