函数组合中的类型推导
Type deduction in function composition
你好,我有一个带有类型参数的类型:
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]
我在 show . var
的 getters
中收到以下错误:
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
都在实现 Show
编辑:在下方更新以回答您的后续问题。
回答你原来的问题,这只是类型检查器需要一点帮助的情况。正如@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]
或者,也可以通过打开 NoMonomorphismRestriction
GHC 扩展,正如@DanielWagner 指出的那样。执行其中任一操作后,以下操作正常:
> map ($ C A1 10) getters
["A1","10"]
> map ($ C B2 10) getters
["B2","10"]
>
如果您对方法的评论是针对 Willem 的,则此签名不会使 getters
成为 "method"。它仍然是类型为 [C a -> String]
的多态表达式(对于具有 Show a
约束的任何类型 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
扩展以便编译,就像以前一样。
你好,我有一个带有类型参数的类型:
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]
我在 show . var
的 getters
中收到以下错误:
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
都在实现 Show
编辑:在下方更新以回答您的后续问题。
回答你原来的问题,这只是类型检查器需要一点帮助的情况。正如@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]
或者,也可以通过打开 NoMonomorphismRestriction
GHC 扩展,正如@DanielWagner 指出的那样。执行其中任一操作后,以下操作正常:
> map ($ C A1 10) getters
["A1","10"]
> map ($ C B2 10) getters
["B2","10"]
>
如果您对方法的评论是针对 Willem 的,则此签名不会使 getters
成为 "method"。它仍然是类型为 [C a -> String]
的多态表达式(对于具有 Show a
约束的任何类型 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
扩展以便编译,就像以前一样。