2014-05-13 49 views
1

我试图做我的功课,但我得到一个语法错误,我不明白。Haskell语法错误与嵌套的ifs

data CTree a b = 
     CNode (CTree a b) b (CTree a b) | -- left, value, right 
     CLeaf a       -- value 
    deriving (Show, Ord) 

-- a) 
-- 

instance (Ord a, Ord b) => Ord (CTree a b) where 

    -- 
    -- Compares two CNode objects 
    -- 
    (CNode left1 v1 right1) `compare` (CNode left2 v2 right2) = 

     -- If the value of the first node is greater than 
     -- the value of the second node, the result is GT. 
     if (v1 > v2) then GT 

     -- If the value of the first node is smaller than 
     -- the value of the second node, the result is LT 
     else if (v2 < v1) then LT 

     -- We must compare the child nodes if the values of 
     -- boths nodes equal. 
     else if (v1 == v2) then 

      if (left1 == left2) then 
       (right1 `compare` right2) 
      else 
       (left1 `compare` left2) 

main = do 
    print "foo" 

错误的是(在main = do行)

解析错误(可能是不正确的缩进或不匹配的括号)

据我所知,还有的比较某些重载函数丢失,但是语法错误不应该源于这个事实。

+1

看来你只是想根据字典顺序进行比较。你可以通过使用比较实例为元组来做到这一点:'compare(CNode left1 v1 right1)(CNode left2 v2 right2)= compare(v1,left1,right1)(v2,left2,right2)' – user2407038

+0

如果你还想写它明确地(而不是使用@ user2407038的技巧):由于你比较'v1'和'v2'所有三种方式,它可能会更清晰(和更有效)使用'case v1'compare' v2 of ... ''而不是嵌套'if's。 –

回答

1

你应该缩进:

if (left1 == left2) then 
    (right1 `compare` right2) 
else 
    (left1 `compare` left2) 

多一个层,并且提供用于相应的if (v1 == v2) thenelse

然后,您应该从deriving中删除Ord,并添加Eq。而且,由于你的b类型为Ord你可以重写你的程序为:

data CTree a b = 
     CNode (CTree a b) b (CTree a b) | 
     CLeaf a 
    deriving (Show, Eq) 

instance (Ord a, Ord b) => Ord (CTree a b) where 
    (CNode _ v1 _) `compare` (CNode _ v2 _) = v1 `compare` v2 

main = do 
    print "foo" 

Live demo

它注意到像你描述它,我已经改变了compare功能的含义为CTree,因为你的函数永远不会返回EQ,这实际上是一个预期值。

但是,如果你想保住你的行为,你可以这样做:

instance (Ord a, Ord b) => Ord (CTree a b) where 
    (CNode left1 v1 right1) `compare` (CNode left2 v2 right2) = 
     if (v1 == v2) then 
      if (left1 == left2) then 
       (right1 `compare` right2) 
      else 
       (left1 `compare` left2) 
     else v1 `compare` v2 

Live demo

4

在你的代码,if (v1 == v2)有一个then分支,但缺少else之一。您应该删除那个if,因为您之前检查了v1 < v2v1 > v2,所以它没有任何用处。