我想做类似的事情:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n
但这不起作用。怎么解决这个?
答案 0 :(得分:7)
几种可能性,Haskell2010方式,
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == maxBound = minBound
| otherwise = succ n
类型由使用决定,两者的类型,maxBound
和minBound
必须是参数的类型。
或者您可以使用ScopedTypeVariables
扩展名,将类型变量放入范围,以便可以在本地类型签名中使用,
{-# LANGUAGE ScopedTypeVariables #-}
succ' :: forall a. (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n
但是,如上所述,这里没有必要。
第三种可能性是使用asTypeOf :: a -> a -> a
,
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound `asTypeOf` n) = minBound `asTypeOf` n
| otherwise = succ n
这里也不需要,但在其他情况下也很有用。
答案 1 :(得分:6)
您不需要类型注释,它们是您获得的错误的来源:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == maxBound = minBound
| otherwise = succ n
(这适用于Haskell 98和Haskell 2010,所以你可以使用任何编译器。)
另外,我稍微缩进|
,因为它们无法与函数的开头对齐;它们是succ'
定义的一部分,而不是独立代码。
以下是一些测试数据:
data Test = A | B | C
deriving (Bounded, Eq, Enum, Show)
test = map succ' [A .. C]
我得到[B,C,A]
。