当我在函数isQuestion
的类型签名中明确提到类型时,GHCi完美地编译它:
isQuestion :: [Char] -> Maybe Bool
isQuestion [] = Nothing
isQuestion xs = Just (last xs == '?')
但是,当我转向“通用”代码时,它不起作用:
isQuestion :: [a] -> Maybe b
isQuestion [] = Nothing
isQuestion xs = Just (last xs == '?')
因为我收到以下错误:
<interactive>:138:17: error:
* Couldn't match type `b' with `Bool'
`b' is a rigid type variable bound by
the type signature for:
isQuestion :: forall a b. [a] -> Maybe b
at <interactive>:136:1-28
Expected type: Maybe b
Actual type: Maybe Bool
* In the expression: Just (last xs == '?')
In an equation for `isQuestion':
isQuestion xs = Just (last xs == '?')
* Relevant bindings include
isQuestion :: [a] -> Maybe b (bound at <interactive>:137:1)
答案 0 :(得分:4)
[a] -> Maybe b
类型是forall a b. [a] -> Maybe b
的简写。但是isQuestion
对所有类型a
和b
都不起作用,它仅在a
为Char
时才有效b
为Bool
。
答案 1 :(得分:4)
首先观察的是
()
只有在last xs == something
元素的范围内有(==)
的定义时,才有效。但由于编译器对xs
一无所知,所以没有这样的事情。您必须将a
缩小为具有相等性的类型的子集:
a
第二个观察结果是isQuestion :: Eq a => [a] -> Maybe b
是代码中的something
(Char
),因此此方法只能在'?'
时使用。相反,您可以将该内容添加为参数:
a ≡ Char
最后,正如已经指出的那样,你有一个具体的返回类型,即isQuestion :: Eq a => a -> [a] -> Maybe b
,作为
Maybe Bool
所以你的功能签名可能是
(==) :: a -> a -> Bool
为了清晰起见编辑了这一段请注意,根据您的业务逻辑,您可能不希望对空字符串进行特殊处理。如果您唯一关心的是字符串是否以问号结尾,那么isQuestion :: Eq a => a -> [a] -> Maybe Bool
和Nothing
实际上意味着同样的事情。在这种情况下,您的功能变为&#34;是或否&#34;问题,你可以删除Just false
:
Maybe
或只是
isQuestion :: Eq a => a -> [a] -> Bool
isQuestion x = isSuffixOf [x]
答案 2 :(得分:2)
参数多态是不子类型或超类型。这是一个声明,值的实现不依赖于部分类型。事实上,该实现适用于任何类型的选择。
您的实施不适用于任何类型选择。仅当a
为Char
且b
为Bool
时才有效。您可以告诉它,因为它使用(== '?')
,这是类型Char -> Bool
的函数。