haskell - 多态类约束实例

标签 haskell types typeclass instances

我想创建所有类型的实例 EnumBounded也是 Random 的一个实例.以下代码执行此操作并且应该可以工作(启用了适当的扩展):

import System.Random

instance (Enum r, Bounded r) => Random r where
   randomR (hi, lo) = inFst toEnum . randomR (fromEnum hi, fromEnum lo)
      where inFst f (x,y) = (f x, y)
   random = randomR (maxBound, minBound)

但我知道这是不好的风格,因为 instance (Enum r, Bounded r) => Random r为所有 r 创建一个实例, 只需对 Enum 进行类型检查和 Bounded而不仅仅是将实例放在 Enum 的类型上和 Bounded .这实际上意味着我正在为所有类型定义一个实例 :( .

另一种方法是我必须编写独立函数来提供我想要的行为,并为我想成为 Random 实例的每种类型编写一些样板文件。 :
randomBoundedEnum :: (Enum r, Bounded r, RandomGen g) => g -> (r, g)
randomBoundedEnum = randomRBoundedEnum (minBound, maxBound)

randomBoundedEnumR :: (Enum r, Bounded r, RandomGen g) => (r, r) -> g -> (r, g)
randomBoundedEnumR (hi, lo) = inFst toEnum . randomR (fromEnum hi, fromEnum lo)
   where inFst f (x,y) = (f x, y)

data Side = Top | Right | Bottom | Left 
   deriving (Enum, Bounded)

-- Boilerplatey :( 
instance Random Side where
   randomR = randomBoundedEnumR
   random = randomBoundedEnum

data Hygiene = Spotless | Normal | Scruffy | Grubby | Flithy
   deriving (Enum, Bounded)

-- Boilerplatey, duplication :(
instance Random Hyigene where
   randomR = randomBoundedEnumR
   random = randomBoundedEnum

有没有更好的选择?我应该如何处理这个问题?我什至不应该尝试这个吗?我是否过度担心样板文件?

最佳答案

是的,正如我刚刚回复了 slightly related question ,您可以使用新类型包装器 - 这是制作此类实例而不会惹恼整个社区的常见且安全的方法。

newtype RandomForBoundedEnum a = RfBE { unRfBE :: a}
instance (Enum a, Bounded a) => Random (RandomForBoundedEnum a) where
    ....

以这种方式,想要使用此实例的用户只需要包装(或解包)调用:
first unRfBE . random $ g :: (Side, StdGen)

关于haskell - 多态类约束实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3945112/

相关文章:

types - 在函数式编程中确定函数的类型

typescript - 将 union 转换为 map

java - 在java中将浮点位解释为long?

scala - 无法在 Scala 工作表中的伴生对象内找到隐式值

haskell - 将 Data.Constraint.Forall 与等式约束一起使用

haskell - 从 COQ : Logical or arity value used 生成 Haskell 代码

haskell - 反射:创建可重置的延迟事件

haskell - 如何有效阅读Yesod错误信息?

haskell - 在 Haskell 项目中添加库

haskell - 帮助解释重叠实例错误消息