我想做点什么:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n
Run Code Online (Sandbox Code Playgroud)
但这不起作用.怎么解决这个?
几种可能性,Haskell2010方式,
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == maxBound = minBound
| otherwise = succ n
Run Code Online (Sandbox Code Playgroud)
类型是根据用途,两者的类型确定的,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
Run Code Online (Sandbox Code Playgroud)
但是,如上所述,这里没有必要.
第三种可能性是使用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
Run Code Online (Sandbox Code Playgroud)
这里不再需要,但在其他情况下可能有用.
您不需要类型注释,它们是您获得的错误的来源:
succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == maxBound = minBound
| otherwise = succ n
Run Code Online (Sandbox Code Playgroud)
(这适用于Haskell 98和Haskell 2010,所以几乎所有编译器都存在.)另外,我缩进|了一点,因为它们无法与函数的开头对齐; 它们是定义的一部分succ',而不是独立代码.
这是一些测试数据:
data Test = A | B | C
deriving (Bounded, Eq, Enum, Show)
test = map succ' [A .. C]
Run Code Online (Sandbox Code Playgroud)
我有[B,C,A].