问题在Haskell中调用数据构造函数

时间:2012-11-10 14:09:29

标签: haskell constructor functional-programming declarative hugs

我正在尝试编写自己的多态列表类型List a,以充当默认库列表。我相信代码是正确的,但我似乎无法在Hugs98中成功调用它。使用List a?类型调用函数和计算非空列表的长度的正确方法是什么?

My Haskell Code is:
data List a = Nil | Cons a (List a)

len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs

提前致谢!

1 个答案:

答案 0 :(得分:2)

我假设您已将该代码保存在名为Lists.hs的文件中

以下是如何在Hugs中调用len函数。

Main> :l Lists
Main> len Nil
0
Main> len (Cons 1 Nil)
1
Main> len (Cons 'a' Nil)
1
Main> len (Cons 'a' (Cons 'b' Nil))
2
Main> len (Cons 'a' (Cons 'b' (Cons 'c' Nil)))
3
但是,括号有点难看。这是一种让它变得更好的方法:

infixr 5 :.
data List a = Nil | a :. (List a) 
    deriving Show

infixr行告诉Hugs构造函数:.应该与右边相关联,因此右边有隐式括号,这意味着

'a' :. 'b' :. Nil  =  'a' :. ('b' :. Nil)

如果你不这样做,拥抱会认为:.左边是同伙,所以会想到

'a' :. 'b' :. Nil  =  ('a' :. 'b') :. Nil

这没有意义 - 你会得到

Main> 'a' :. 'b' :. Nil
ERROR - Type error in application
*** Expression     : 'a' :. 'b'
*** Term           : 'b'
*** Type           : Char
*** Does not match : List a

或者更令人困惑的是,如果是数字,它会尝试从列表中创建一个数字:

Main> 1 :. 2 :. Nil
ERROR - Cannot infer instance
*** Instance   : Num (List a)
*** Expression : 1 :. 2 :. Nil

无论如何,我们做了infixr 5 :.事情,所以这不会发生。我选择了5的优先级,因为这是:在标准前奏中的含义。现在我们可以编辑len以应对新定义:

len :: List a -> Int
len Nil = 0
len (_ :. xs) = 1 + len xs

这样你就得到了

Main> len (4 :. 5 :. 6:. Nil)
3

或者如果您愿意,

Main> len $ 4 :. 5 :. 6:. Nil
3

(你可以做到

infixr 5 `Cons`

相反,但我不认为这很好。)