功能组成的类型推导

时间:2018-07-16 11:32:37

标签: haskell type-parameter

你好,我有一个带有类型参数的类型:

data A=A1| A2 deriving (Show)
data B=B1| B2 deriving(Show)
data C a=C{var::a,var2::Int}

getters=[show . var,show .var2]

我在getters的{​​{1}}中收到以下错误:

show . var

我是否必须明确声明类型,例如:Ambiguous type variable `a0' arising from a use of `show' prevents the constraint `(Show a0)' from being solved. Relevant bindings include getters:: [Worker a0 -> String] 。我并不能真正理解该错误,因为show. (var::B)A这两个类型都在实现B < / p>

1 个答案:

答案 0 :(得分:2)

编辑:下面进行了更新,以回答您的后续问题。

要回答您的原始问题,这只是类型检查器需要一点帮助的情况。您可以按照@WillemVanOnsem的建议,通过为getters添加显式签名来使代码进行类型检查:

data A = A1 | A2 deriving (Show)
data B = B1 | B2 deriving (Show)
data C a = C { var :: a, var2 :: Int }

getters :: (Show a) => [C a -> String]
getters = [show . var, show . var2]

,或者,如@DanielWagner指出的那样,通过打开NoMonomorphismRestriction GHC扩展名。完成上述任何一项操作后,以下工作正常:

> map ($ C A1 10) getters
["A1","10"]
> map ($ C B2 10) getters
["B2","10"]
> 

如果您对方法的评论是针对Willem的,则此签名不会使getters成为“方法”。它仍然是类型[C a -> String]的多态表达式(对于任何受a约束的类型Show a而言)。

更新:根据您的评论,您认为要定义一个数据类型,该数据类型对一个或多个字段的类型具有约束。 (您实际上不是真的想要这样做-您只是以为您愿意-但我是谁来阻止您?)

因此,要执行此操作,您需要启用DatatypeContexts扩展名并输入:

{-# LANGUAGE DatatypeContexts #-}

class Mytypeclass a where
  whatever :: a -> String

data Mytypeclass a => MyType a = M { var :: a, var2 :: a }

编译器将生成警告,提示该扩展名已被弃用,因为该扩展名被广泛认为是错误功能,已从语言中删除。

现在,您可以定义:

getters = [whatever . var, whatever . var2]

这将给您一个错误,尽管错误消息与以前不同,之后您可以添加签名:

getters :: (Mytypeclass a) => [MyType a -> String]
getters = [whatever . var, whatever . var2]

或像以前一样启用NoMonomorphismRestriction扩展名以便对其进行编译。