我想做类似的事情:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n
但这不起作用。如何解决这个问题?
我想做类似的事情:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n
但这不起作用。如何解决这个问题?
几种可能性,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
同样,这里不需要它,但在其他情况下可能很有用。
您不需要类型注释,它们是您得到的错误的来源:
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]
。