1

我想做类似的事情:

succ' :: (Bounded a, Eq a, Enum a) => a -> a
succ' n
| n == (maxBound :: a) = minBound :: a
| otherwise = succ n

但这不起作用。如何解决这个问题?

4

2 回答 2

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

同样,这里不需要它,但在其他情况下可能很有用。

于 2012-11-14T21:50:07.583 回答
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]

于 2012-11-14T21:49:21.127 回答