我正在尝试执行以下操作:
-- enum which wraps arround class (Enum a, Bounded a) => CyclicEnum a where next, prev :: a -> a -- for equatable types this is readily implemented instance (Enum a, Bounded a, Eq a) => CyclicEnum a where next x | x == maxBound = minBound | otherwise = succ x prev x | x == minBound = maxBound | otherwise = pred x
但是除非我同时启用FlexibleInstances和UndecidableInstances,否则这不会编译,这似乎不对.什么是正确的方法(即,通常使用的方法,最好没有语言扩展)来做这样的事情?有吗?
首先,没有任何错误FlexibleInstances
- 它只是禁用标准Haskell的一些限制,这些限制主要是出于历史原因,也许是为了使编译器更容易编写.但是,如果你只使用GHC - 几乎每个人都这样做 - 那么没有真正的理由不使用FlexibleInstances
.
UndecidableInstances
更值得商榷,但在某些情况下,使用它也绝对可以.
但是,在您的示例中,我认为不需要定义任何新的类型类!为什么不直接定义为自由函数,
next, prev :: (Enum a, Bounded a, Eq a) => a -> a next x | x == maxBound = minBound | otherwise = succ x prev x | x == minBound = maxBound | otherwise = pred x
好.可能你的意图是CyclicEnum
除了通用实例之外还添加其他实例.但这实际上是不可能的!即使有UndecidableInstances
.它需要OverlappingInstances
(或者更确切地说,Overlappable
pragma),但重叠的实例实际上不是你应该使用的东西,因为你可以.