1

我正在尝试编写自己的多态列表类型 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

提前致谢!

4

1 回答 1

2

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

这是len在 Hugs 中调用函数的方法。

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)

如果你不放这个,Hugs 会假设:.联想到左边,所以它会认为

'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`

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

于 2012-11-10T16:40:11.510 回答