У меня есть этот бит кода:
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 ()
. Монады должны совпадать —m
должно быть равноRVar
, что не так. Вы не можете не использовать сигнатуру(MonadRandom m, MonadState s m) => s -> m ()
, в частности потому, что функцияuniform
реализована для RVar, а не для какого-либо MonadRandom. - person user2407038   schedule 16.12.2015MonadState s m => s -> RVarT m ()
, просто используйтеuniformT :: Distribution Uniform a => a -> a -> RVarT m a
. - person user2407038   schedule 16.12.2015