类型问题与Haskell概率Monad

时间:2014-11-12 06:21:16

标签: haskell monads typeclass

我正在尝试在haskell中为离散随机变量编写一个monad。类型类看起来像这样:

{- LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

class (Num w, Monad m) => MonadDiscrete w m where
  sample :: [(a, w)] -> m a

我想做两个这样的例子。第一个就像列表monad:

newtype Discrete w a = Discrete [(a, w)]

instance (Num w) => Monad (Discrete w) where
  ...

instance (Num w) => MonadDiscrete w (Discrete w) where
  sample = Discrete

第二种是在MonadRandom中使用PRNG:

instance (MonadRandom m) => MonadDiscrete Rational m where
  sample = fromList

但是,如果我尝试做类似的事情:

x :: (Num w, MonadDiscrete w m) => m String
x = sample [("x", 1)]

GHC给了我一个错误:

  

无法演绎(MonadDiscrete w0 m)     由it' from the context (MonadDiscrete w m) bound by the inferred type for的歧义检查引起的:#MonadDiscrete w m => m [Char]     时间:7:1-17   类型变量w0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Num w => MonadDiscrete w (Discrete w) -- Defined at lib/Discrete.hs:64:10 instance Control.Monad.Random.Class.MonadRandom m => MonadDiscrete Rational m -- Defined at lib/Discrete.hs:58:10 When checking that它'     具有推断类型`forall w(m :: * - > *)。                            MonadDiscrete w m =>                            m [Char]'   可能原因:推断类型不明确

我尝试了各种各样的事情,包括添加FunDeps或制作相关类型,但都失败了。

2 个答案:

答案 0 :(得分:1)

问题在于声明

class (Num w, Monad m) => MonadDiscrete w m where
    sample :: [(a, w)] -> m a

没有表达这样的事实:对于给定的离散概率monad,表示权重的类型的选择是固定的。例如,在Discrete示例中,对于w的任何选择,Discrete w monad只能处理w类型的概率权重。

由于上述声明中未对此进行说明,因此可以定义两个MonadDiscrete个实例,这些实例仅在w的选择中有所不同,但在m的选择中则不同。这意味着 在sample的定义中,无法单独从MonadDiscrete解析m个实例。

解决此问题的正确方法是使用函数依赖关系或MonadDiscrete - 关联类型系列来表示m的选择唯一地确定w的选择。这是一个使用函数依赖的示例:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}

class (Num w, Monad m) => MonadDiscrete w m | m -> w where
    sample :: [(a, w)] -> m a

newtype Discrete w a = Discrete [(a, w)]

instance (Num w) => Monad (Discrete w)
instance (Num w) => MonadDiscrete w (Discrete w)

x :: (Num w, MonadDiscrete w m) => m String
x = sample [("x", 1)]

由于m确定w,即使w类型中没有出现x,它仍然可以唯一解析,所以正确{{1}可以选择实例。

以下是使用类型系列的相同解决方案:

MonadDiscrete

这个感觉有点不同,因为这里不是拼写出依赖关系,而是简单地说作为{-# LANGUAGE TypeFamilies, FlexibleContexts #-} class (Num (Weight m), Monad m) => MonadDiscrete m where type Weight m :: * sample :: [(a, Weight m)] -> m a newtype Discrete w a = Discrete [(a, w)] instance (Num w) => Monad (Discrete w) instance (Num w) => MonadDiscrete (Discrete w) where type Weight (Discrete w) = w sample = undefined x :: (MonadDiscrete m) => m String x = sample [("x", 1)] 实例的部分是说什么类型代表MonadDiscrete s。

答案 1 :(得分:0)

我想我已经发现我实际上并不想要

instance (MonadRandom m) => MonadDiscrete Rational m where
  sample = fromList

但相反:

instance RandomGen g => MonadDiscrete Rational (Rand g) where
  sample = fromList

由于我的目标是使用特定的现有实现,而不是所有可能的MonadRandom实例。