【发布时间】:2019-10-29 19:09:02
【问题描述】:
如何编写一个通用函数run,它接受某个monad转换器的对象,并调用相应的函数?
给定run s,
- 如果
s是StateT,则run = runStateT - 如果
s是ReaderT,run = runReaderT - 如果
s是MaybeT,则run = runMaybeT
我已经尝试创建一个类型类Runnable:
:set -XMultiParamTypeClasses
:set -XFlexibleInstances
class Runnable a b where
run :: a -> b
(//) :: a -> b
(//) = run
instance Runnable (StateT s m a) (s -> m (a, s)) where
run = runStateT
instance Runnable (ReaderT r m a) (r -> m a) where
run = runReaderT
但是当我尝试使用run 时,它不起作用。例如,我们定义simpleReader,它在读取时只返回10:
simpleReader = ReaderT $ \env -> Just 10
runReaderT simpleReader ()
这会像预期的那样输出Just 10。
但是,当我尝试使用 run 时,它给了我一个错误:
run simpleReader ()
<interactive>:1:1: error:
• Non type-variable argument in the constraint: Runnable (ReaderT r Maybe a) (() -> t)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall r a t. (Runnable (ReaderT r Maybe a) (() -> t), Num a) => t
如果我按照它的建议启用FlexibleContexts,我会得到一个不同的错误:
<interactive>:1:1: error:
• Could not deduce (Runnable (ReaderT r0 Maybe a0) (() -> t))
(maybe you haven't applied a function to enough arguments?)
from the context: (Runnable (ReaderT r Maybe a) (() -> t), Num a)
bound by the inferred type for ‘it’:
forall r a t. (Runnable (ReaderT r Maybe a) (() -> t), Num a) => t
at <interactive>:1:1-19
The type variables ‘r0’, ‘a0’ are ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall r a t. (Runnable (ReaderT r Maybe a) (() -> t), Num a) => t
【问题讨论】:
-
怎么不工作?
-
我添加了一些信息来解释我遇到了什么错误
标签: haskell monads typeclass monad-transformers