Bru*_*rry 6 monads haskell either
我知道可以更改包装类型,以便您可以拥有
f :: (a -> m b)
g :: (b -> m c)
f >>= g :: (a -> m c)
Run Code Online (Sandbox Code Playgroud)
但是有可能改变m吗?如果m是MonadError,由一个实现既Either ErrorA和Either ErrorB,可不知何故,我把它们连?显然我不能直接链接它们,因为它的类型是Left什么?但是,我遇到的情况是我最后show都要打电话,但我找不到更好的解决方案
case mightFail1 of
Left e -> show e
Right v -> either show doStuff mightFail2
Run Code Online (Sandbox Code Playgroud)
在没有我必须明确检查的情况下,它无法正确使用在第一个错误处停止的monadic行为.
J. *_*son 11
"改变容器"的整个概念被称为"自然变换".具体来说,我们需要一个能够在不影响内部变形的情况下转换容器的功能.我们可以通过使用确保类型系统中的情况forall.
-- natural transformation
type (m :~> n) = forall a. m a -> n a
Run Code Online (Sandbox Code Playgroud)
然后这些可以随时应用.例如,如果您可以转换,那么您可以ErrorA -> ErrorB进行一般操作
mapE :: (e -> e') -> (Either e :~> Either e')
mapE f (Left e) = Left (f e)
mapE _ (Right a) = a
Run Code Online (Sandbox Code Playgroud)
您甚至可以使用类型运算符和求和类型.
-- a generic sum type
infixr 9 :+:
newtype (a :+: b) = Inl a | Inr b
liftE :: (Either e :~> Either (e' :+: e))
liftE = mapE Inr
Run Code Online (Sandbox Code Playgroud)
Bifunctors实现了大致相同的效果,但它们是一种完全不同的方式来查看问题.它们不是通常更换容器,而是影响容器本身的另一个协变参数(或索引).因此,Bifunctor动作总是被视为自然变换,但NT更为通用.
在monadic链中不可能这样做.
请注意,这根本不是真的关心Monad:你不会以任何方式绑定参数中的嵌套monadic动作Left或类似的东西,但你只是在改变参数本身.它基本上是仿函数操作fmap,但是在Left而不是Right部分:
fmap :: (r->?) -> Either l r -> Either l ?
fmapLeft :: (l->?) -> Either l r -> Either ? r
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,具有该特定签名的功能似乎不存在.然而,这个带有两个协变参数的仿函数的想法显然比仅仅更普遍Either,而且确实有专门的类.它有(IMO相当不幸的命名,冲突Arrow)
Data.Bifunctor.first :: (a -> b) -> p a c -> p b c
Run Code Online (Sandbox Code Playgroud)
其中擅长于
first :: (a -> b) -> Either a c -> Either b c
Run Code Online (Sandbox Code Playgroud)
所以你可以使用
f :: (Show a) => (Either a b) -> (Either String b)
f = first show
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
737 次 |
| 最近记录: |