我正在尝试从第一原理-26.3-实例5编写针对Haskell编程的解决方案。
问题是要编写适用于monad变压器变体EitherT的两种同构形式。函数的类型应为:
eitherT :: Monad m => (e -> m c) -> (a -> m c) -> EitherT e m a -> m c
作为参考,这是本书中定义的EitherT新类型:
newtype EitherT e m a = --why does the book use e a for the type parameters instead of a b? Error type?
EitherT {runEitherT :: m (Either e a)}
此外,我有一个正在工作的instance Monad m => Monad (EitherT e m)
,以及之前的Functor和Applicative。
问题说明中给出的类型签名表明,我将需要使用m或可能的(EitherT e m)的Monadic功能。但是,我写了一个只使用fmap的版本,我认为这样可以起作用:
eitherT :: Monad m => (e -> m c) -> (a -> m c) -> EitherT e m a -> m c
eitherT fe fa = fmap (either fe fa) . runEitherT
这不能编译。具体来说,编译器抱怨我构造了无限类型c〜mc(下面的完整输出)。我将以此为线索,说明该问题应通过一些单调函数来解决。但是,我想了解我的方法在该结构中的添加位置。到目前为止,我还不能。
这是我编写代码的理由:
runEitherT :: EitherT e m a -> m (Eihter e a)
either fe fa :: Either e a -> c
fmap (either fe fa) :: m (Either e a) -> m c
fmap (either fe fa) . runEitherT :: EitherT e m a -> m c
这似乎与eitherT fe fa
的类型完全匹配。
有人可以指出我哪里出了问题吗?
完整的错误消息:
Haskell> :l EitherT.hs
[1 of 1] Compiling EitherT ( EitherT.hs, interpreted )
EitherT.hs:36:17: error:
* Occurs check: cannot construct the infinite type: c ~ m c
Expected type: EitherT e m a -> m c
Actual type: EitherT e m a -> m (m c)
* In the expression: fmap (either fe fa) . runEitherT
In an equation for `eitherT':
eitherT fe fa = fmap (either fe fa) . runEitherT
* Relevant bindings include
fa :: a -> m c (bound at EitherT.hs:36:12)
fe :: e -> m c (bound at EitherT.hs:36:9)
eitherT :: (e -> m c) -> (a -> m c) -> EitherT e m a -> m c
(bound at EitherT.hs:36:1)
|
36 | eitherT fe fa = fmap (either fe fa) . runEitherT
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
答案 0 :(得分:4)
好吧,当我查看问题的格式时,我找到了答案。万一它对其他人有帮助,这里是:
如果fe
和fa
的类型为(a -> c)
而不是(a -> m c)
的形式,则我的解决方案有效。
更改任一T的类型签名以反映出可以编译代码的特征。我的推理中的特定缺陷在步骤2中,应显示为:
either fe fa :: Either e a -> m c