Haskell:类型变量和泛型类型

时间:2018-04-11 00:05:26

标签: function haskell types transparency referential

当我在函数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)

3 个答案:

答案 0 :(得分:4)

[a] -> Maybe b类型是forall a b. [a] -> Maybe b的简写。但是isQuestion对所有类型ab都不起作用,它仅在aChar时才有效bBool

答案 1 :(得分:4)

首先观察的是

()
只有在last xs == something 元素的范围内有(==)的定义时,

才有效。但由于编译器对xs一无所知,所以没有这样的事情。您必须将a缩小为具有相等性的类型的子集:

a

第二个观察结果是isQuestion :: Eq a => [a] -> Maybe b 是代码中的somethingChar),因此此方法只能在'?'时使用。相反,您可以将该内容添加为参数:

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)

参数多态是子类型或超类型。这是一个声明,值的实现不依赖于部分类型。事实上,该实现适用于任何类型的选择。

您的实施不适用于任何类型选择。仅当aCharbBool时才有效。您可以告诉它,因为它使用(== '?'),这是类型Char -> Bool的函数。