У меня есть этот кусок кода:Использование 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
и написать:
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
Вы писали '(Uniform 0 1 :: RVar Double)', но вы объявили тип функции, чтобы быть 'м()' , Монады должны совпадать - '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