Haskell 为具有函数和 Either 的 Monad 定义 return
Haskell define return for Monad with function and Either
如何在 Haskell 中为这种数据类型定义 monad?它基本上是一个 salsa 解释器。而且我无法弄清楚 return 应该是什么样子。这让我发疯...
newtype Salsa a = Salsa {
runSalsa :: Context -> Either String (a, Context, Animation)}
instance Monad Salsa where
return a = Salsa $ ..........
instance Functor Salsa where
fmap = liftM
instance Applicative Salsa where
pure = return
(<*>) = ap
http://ap-e2015.onlineta.org/assignments/assignment-1-salsa-interpreter.html
你需要一个接受 Context
的函数,所以使用 lambda \con ->
.
到目前为止,您没有任何失败的事情,所以您总能成功。 Right
.
a
由对 return
的调用提供。 (a,
.
Context
由对 lambda 的调用提供。 con,
.
现在您必须决定要包含的动画,我猜 none。 [])
。 (请注意,我不记得那里的确切语法,但我认为这是正确的)。
把它们放在一起你得到:
return a = Salsa $ \con -> Right (a, con, [])
现在出现了复杂的情况,您必须处理绑定 (>>=
)。
嗯,我对 Salsa 一无所知,但在阅读了 Guvante 预示实施难度的答案后 >>=
,我认为这将是一个有趣的练习。由于我不知道 Salsa 的 Context 或 Animation 类型是什么,我决定只对它们进行参数化,我认为效果相当好:作为 >>=
的实现者,Context 的类型对我们来说可能是完全不透明的,我们只需要 Animation
成为一个幺半群:
newtype Salsa ctx error anim a = Salsa {
runSalsa :: ctx -> Either error (a, ctx, anim)
}
instance Monoid anim => Monad (Salsa ctx error anim) where
return x = Salsa $ \ctx -> return (x, ctx, mempty)
(Salsa m) >>= f = Salsa m'
where m' ctx = m ctx >>= handle
handle (x, ctx, anims) = let (Salsa f') = f x
merge (a, b, c) = (a, b, mappend anims c)
in merge <$> f' ctx
instance Monoid anim => Functor (Salsa ctx error anim) where
fmap = liftM
instance Monoid anim => Applicative (Salsa ctx error anim) where
pure = return
(<*>) = ap
这很笼统,我可以想出如何制作它,但我对 handle
的实现仍然不完全满意:似乎必须有更好的方法来组合动画结果比让一个函数然后 fmapping 它,但我找不到更漂亮的东西。
顺便说一下,我认为这个 (a, Context, Animation)
组有一个真实的数据类型会更好,而不仅仅是一个元组。然后你可以,例如,给它一个 Functor 实例并简化 handle
的实现,删除 merge
函数并只写
mappend anims <$> f' ctx
帮助自己typed holes:在卡住的地方写下划线:
instance Monad Salsa where
return a = Salsa $ _
编译器告诉你这里需要一个函数
Found hole ‘_’
with type: Context -> Either String (a, Context, Animation)
现在您可以按照自己的方式工作了
instance Monad Salsa where
return a = Salsa $ \x -> _
对于>>=
,做几乎相同的事情:
(Salsa s) >>= f = Salsa $ \x -> _
编译器输出
Found hole ‘_’ with type: Either String (b, Context, Animation)
Relevant bindings include
con :: Context
f :: a -> Salsa b
s :: Context -> Either String (a, Context, Animation)
所以,s
是一个需要 Context
的函数,但是我们的 con
提供了一个,把它放在一起:
(Salsa s) >>= f = Salsa $ \con -> let s' = s con in _
...
s' :: Either String (a, Context, Animation)
(bound at Review.hs:12:43)
f :: a -> Salsa b (bound at Review.hs:12:19)
所以我们需要 s'
中的 a
东西来提供给 f
。 s'
上的模式匹配(重命名时):
(Salsa salsaFunction1) >>= f = Salsa $ \context1 ->
let salsaResult1 = salsaFunction1 context1
in case salsaResult1 of
Left errorMsg -> Left errorMsg
Right (a, context2, animation1) ->
let Salsa salsaFunction2 = f a
salsaResult2 = salsaFunction2 context2
in _
salsaFunction2 :: Context -> Either String (b, Context, Animation)
animation1 :: Animation
context2 :: Context
a :: a
salsaResult1 :: Either String (a, Context, Animation)
context1 :: Context
f :: a -> Salsa b
salsaFunction1 :: Context -> Either String (a, Context, Animation)
所以,我们还有一个 salsaFunction2
,还有一个未使用的 context2
。您已经看到了如何将它们放在一起:进行另一个案例分析,在 Right
案例中提供 context3
,monadic 结果 b
并结合两个动画以提供最终的 Either String (b, Context, Animation)
一次又一次地看到:
Found hole ‘_’ with type: Either String (b, Context, Animation)
如何在 Haskell 中为这种数据类型定义 monad?它基本上是一个 salsa 解释器。而且我无法弄清楚 return 应该是什么样子。这让我发疯...
newtype Salsa a = Salsa {
runSalsa :: Context -> Either String (a, Context, Animation)}
instance Monad Salsa where
return a = Salsa $ ..........
instance Functor Salsa where
fmap = liftM
instance Applicative Salsa where
pure = return
(<*>) = ap
http://ap-e2015.onlineta.org/assignments/assignment-1-salsa-interpreter.html
你需要一个接受 Context
的函数,所以使用 lambda \con ->
.
到目前为止,您没有任何失败的事情,所以您总能成功。 Right
.
a
由对 return
的调用提供。 (a,
.
Context
由对 lambda 的调用提供。 con,
.
现在您必须决定要包含的动画,我猜 none。 [])
。 (请注意,我不记得那里的确切语法,但我认为这是正确的)。
把它们放在一起你得到:
return a = Salsa $ \con -> Right (a, con, [])
现在出现了复杂的情况,您必须处理绑定 (>>=
)。
嗯,我对 Salsa 一无所知,但在阅读了 Guvante 预示实施难度的答案后 >>=
,我认为这将是一个有趣的练习。由于我不知道 Salsa 的 Context 或 Animation 类型是什么,我决定只对它们进行参数化,我认为效果相当好:作为 >>=
的实现者,Context 的类型对我们来说可能是完全不透明的,我们只需要 Animation
成为一个幺半群:
newtype Salsa ctx error anim a = Salsa {
runSalsa :: ctx -> Either error (a, ctx, anim)
}
instance Monoid anim => Monad (Salsa ctx error anim) where
return x = Salsa $ \ctx -> return (x, ctx, mempty)
(Salsa m) >>= f = Salsa m'
where m' ctx = m ctx >>= handle
handle (x, ctx, anims) = let (Salsa f') = f x
merge (a, b, c) = (a, b, mappend anims c)
in merge <$> f' ctx
instance Monoid anim => Functor (Salsa ctx error anim) where
fmap = liftM
instance Monoid anim => Applicative (Salsa ctx error anim) where
pure = return
(<*>) = ap
这很笼统,我可以想出如何制作它,但我对 handle
的实现仍然不完全满意:似乎必须有更好的方法来组合动画结果比让一个函数然后 fmapping 它,但我找不到更漂亮的东西。
顺便说一下,我认为这个 (a, Context, Animation)
组有一个真实的数据类型会更好,而不仅仅是一个元组。然后你可以,例如,给它一个 Functor 实例并简化 handle
的实现,删除 merge
函数并只写
mappend anims <$> f' ctx
帮助自己typed holes:在卡住的地方写下划线:
instance Monad Salsa where
return a = Salsa $ _
编译器告诉你这里需要一个函数
Found hole ‘_’
with type: Context -> Either String (a, Context, Animation)
现在您可以按照自己的方式工作了
instance Monad Salsa where
return a = Salsa $ \x -> _
对于>>=
,做几乎相同的事情:
(Salsa s) >>= f = Salsa $ \x -> _
编译器输出
Found hole ‘_’ with type: Either String (b, Context, Animation)
Relevant bindings include
con :: Context
f :: a -> Salsa b
s :: Context -> Either String (a, Context, Animation)
所以,s
是一个需要 Context
的函数,但是我们的 con
提供了一个,把它放在一起:
(Salsa s) >>= f = Salsa $ \con -> let s' = s con in _
...
s' :: Either String (a, Context, Animation)
(bound at Review.hs:12:43)
f :: a -> Salsa b (bound at Review.hs:12:19)
所以我们需要 s'
中的 a
东西来提供给 f
。 s'
上的模式匹配(重命名时):
(Salsa salsaFunction1) >>= f = Salsa $ \context1 ->
let salsaResult1 = salsaFunction1 context1
in case salsaResult1 of
Left errorMsg -> Left errorMsg
Right (a, context2, animation1) ->
let Salsa salsaFunction2 = f a
salsaResult2 = salsaFunction2 context2
in _
salsaFunction2 :: Context -> Either String (b, Context, Animation)
animation1 :: Animation
context2 :: Context
a :: a
salsaResult1 :: Either String (a, Context, Animation)
context1 :: Context
f :: a -> Salsa b
salsaFunction1 :: Context -> Either String (a, Context, Animation)
所以,我们还有一个 salsaFunction2
,还有一个未使用的 context2
。您已经看到了如何将它们放在一起:进行另一个案例分析,在 Right
案例中提供 context3
,monadic 结果 b
并结合两个动画以提供最终的 Either String (b, Context, Animation)
一次又一次地看到:
Found hole ‘_’ with type: Either String (b, Context, Animation)