0
我有這段代碼:使用MonadRandom與MonadState
import Data.Random
import Control.Monad.State
foo :: s -> StateT s RVar()
foo s = do
p <- lift $ (uniform 0 1 :: RVar Double)
if p > 0.5 then put s else return()
而且我想重構其簽名是形式:
foo :: (MonadState s m, RandomSource m s) => s -> m()
我以爲我可以裝備RVar
與MonadState
功能:
{- LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
instance MonadState s m => MonadState s (RVarT m) where
get = lift get
put = lift . put
state = lift . state
and write:
foo :: (MonadState s m, RandomSource m s) => s -> m()
foo s = do
p <- (uniform 0 1 :: RVar Double)
if p > 0.5 then put s else return()
但我得到這個莫名其妙的錯誤:
Couldn't match type ‘m’
with ‘t0 (RVarT Data.Functor.Identity.Identity)’
‘m’ is a rigid type variable bound by
the type signature for
foo :: (MonadState s m, RandomSource m s) => s -> m()
at ApproxMedian.hs:99:8
Expected type: m Double
Actual type: t0 (RVarT Data.Functor.Identity.Identity) Double
Relevant bindings include
foo :: s -> m() (bound at ApproxMedian.hs:100:1)
In a stmt of a 'do' block: p <- lift $ (uniform 0 1 :: RVar Double)
In the expression:
do { p <- lift $ (uniform 0 1 :: RVar Double);
if p > 0.5 then put s else return() }
In an equation for ‘foo’:
foo s
= do { p <- lift $ (uniform 0 1 :: RVar Double);
if p > 0.5 then put s else return() }
Failed, modules loaded: Core, Statistics.
請解釋錯誤並有助於使更多的普通簽名可能嗎?
如果我想做的事:
foo :: (MonadRandom m, MonadState s m) => s -> m()
我將如何實現呢?我不能再使用uniform
。因爲它鎖定我的簽名RVar a
,但我真的想MonadRandom m => m a
, 或者至少是Monad m => RVarT m a
你寫'(統一0 1 :: RVAR雙人間)',但你聲明的函數的類型爲'M()' 。 monads必須匹配 - 「m」必須等於「RVar」,而不是。你可以不使用'(MonadRandom m,MonadState s m)=> s - > m()'簽名,因爲'uniform'函數是爲RVar實現的,而不是用於任何MonadRandom。 – user2407038
你可以有'MonadState s m => s - > RVarT m()',當然,只需使用'uniformT :: Distribution Uniform a => a - > a - > RVarT m a'。 – user2407038