我一直在尝试做类似的事情:
f :: (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [minBound :: a ..] , bs <- x somefunction as]
但是那里的minbound似乎没有用。我怎么能得到它?
答案 0 :(得分:6)
您需要启用ScopedTypeVariables
扩展名并使用显式forall
s:
{-# ScopedTypeVariables #-}
f :: forall a b . (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [minBound :: a ..] , bs <- x somefunction as]
如果没有这个,在Haskell中,每个类型的签名都独立于其他签名进行解释。这就是a
中的minBound :: a
与上面签名中的a
无关。
如果你真的想坚持不使用扩展,你可以编写一个辅助功能:
myBound :: Bounded a => A a b -> a
myBound x = minBound -- does not really depend on x
f :: (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [myBound x ..] , bs <- x somefunction as]
在这种特殊情况下,正如@dfeuer在下面指出的那样,有一个更简单的解决方案。我们只需删除minBound
上的类型注释:
-- no extensions
f :: (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [minBound ..] , bs <- x somefunction as]
这是因为列表推导输出了对(as,bs)
,因此Haskell可以看到as
必须具有类型a
,并且minBound
必须属于同一类型as
。