Haskell中的安全和多态Enum

时间:2016-11-11 13:25:40

标签: haskell enums polymorphism

我正在尝试编写不安全Enum函数的完整版本:

predMay :: Enum a => a -> Maybe a
succMay :: Enum a => a -> Maybe a
toEnumMay :: Enum a => Int -> Maybe a

我的问题是,如果Enum也是Bounded,则不安全的功能只是部分功能,因此在这两种情况下安全版本应该有不同的形式:

predMayUnboundedEnum :: Enum a => a -> Maybe a
predMayUnboundedEnum = Just . pred

predMayBoundedEnum :: (Enum a, Bounded a) => a -> Maybe a
predMayBoundedEnum x
  | fromEnum x == fromEnum (minBound `asTypeOf` x) = Nothing
  | otherwise  = Just (pred x)

我必须得到我想要的功能的最好的想法是使用另一个类型类:

class Enum a => SafeEnum a where
  predMay :: a -> Maybe a
instance Enum a => SafeEnum a where
  predMay = predMayUnboundedEnum
instance (Enum a, Bounded a) => SafeEnum a where
  predMay = predMayBoundedEnum

但这导致了对Duplicate instance declarations的抱怨。

我在这里有正确的想法,还是有更好的方法来解决这个问题?还有其他人已经这样做了吗? (我知道包prelude-safeenum},但Enum对我来说的主要优势是我们可以deriving它。)这些安全功能是否可行,或{{1}在野外太毛茸茸,不能让这么简单的解决方案安全吗?

1 个答案:

答案 0 :(得分:5)

这不可能。请记住,Haskell类型类是 open 。您的提案需要根据类型是否属于Bounded类来执行不同的操作。但是你永远不会知道不属于的类型。 (好吧,可以知道,例如Integer必须没有Bounded个实例,但编译器不能。没有什么能阻止你定义一个除了常识之外的废话instance Bounded Integer where {minBound = 7; maxBound = 3}。)

获取正确实例的唯一可靠方法是在有界或无效中手动对类型进行排序。这可以简单地完成,尤其是默认情况下:

class Enum a => SafeEnum a where
  predMay :: a -> Maybe a
  predMay = predMayUnboundedEnum

instance SafeEnum Integer
instance SafeEnum Rational
instance SafeEnum Int where predMay = predMayBoundedEnum
...