我遇到了一个障碍,试图弄清楚为什么我不能编译以下代码。我正在定义几个函数以使用“ snoc”列表。 headS正常工作,但是在tailS函数中,我无法返回NilS,我想知道为什么。我知道这可能是一个非常基本的问题,但是我已经尝试使用谷歌搜索,但感到更加困惑。希望你能帮助我了解我在想什么。这是我的代码:
data ListS a = NilS
|Snoc (ListS a) a deriving Show
headS :: ListS a -> a
headS NilS = error "Empty List"
headS (Snoc NilS a) = a
headS (Snoc a b) = headS a
tailS :: ListS a -> a
tailS NilS = error "Empty List"
tailS (Snoc NilS a) = NilS
我收到以下错误:
* Couldn't match expected type `a' with actual type `ListS a0'
`a' is a rigid type variable bound by
the type signature for:
tailS :: forall a. ListS a -> a
at Ejercicio01.hs:9:1-21
* In the expression: NilS
In an equation for `tailS': tailS (Snoc NilS a) = NilS
* Relevant bindings include
a :: a (bound at Ejercicio01.hs:11:18)
tailS :: ListS a -> a (bound at Ejercicio01.hs:10:1)
|
11 | tailS (Snoc NilS a) = NilS
| ^^^^
Failed, no modules loaded.
提前感谢您的时间,
答案 0 :(得分:3)
那么编译器是正确的。您的函数的类型签名是:
tailS :: ListS a -> a
因此,输出类型应为a
。但是在这里,您将其写为返回值NilS
。现在NilS
是ListS a
类型的数据构造函数。因此两者不匹配:您的签名表明您将返回“列表”类型的 element ,但是在函数定义中,您将返回一个列表(实际上可能会包装其他类型的元素)
您可能想要返回a
元素,而不是NilS
,所以:
tailS :: ListS a -> a
tailS NilS = error "Empty List"
tailS (Snoc NilS a) = a
但是还有另一个问题。如果我们使用-Wincomplete-patterns
进行编译,则编译器将告诉您存在未涵盖的模式:Snoc (Snoc _ _) _
模式。在最后一行中,您写了tailS (Snoc NilS a)
,因此将其限制为Snoc
的第一项为NilS
。不管“前缀列表”是什么,这都是没有必要的,尾部始终是第二个参数,因此我们可以使用以下方法解决此问题:
tailS :: ListS a -> a
tailS NilS = error "Empty List"
tailS (Snoc _ a) = a