提取嵌套的 ExceptION monad 转换器的左值
Extract left values of nested ExceptT monad transfomers
是否可以创建具有以下签名的函数?
ExceptT A (ExceptT B m) () -> ExceptT B m A
我的想法是这样的,因为 x
是上述函数的参数(而且我很讨厌 monad,所以它很可能是错误的)。
runExceptT x :: ExceptT B m (Either A ())
但是后来我坚持得到像 Either A () -> A
这样的东西,它本质上必须考虑 Right
,因此要么失败,要么 return A
的某个常数(我没有)。
但是,我知道 x
的原始值恰好是左值之一,否则定义将无限循环。
简答:那不可能。
长答案:ExceptT e m a
包含一个 m (Either e a)
,因此 ExceptT A (ExceptT B m) ()
包含一个 ExceptT B m (Either A ())
,后者又包含一个 m (Either B (Either A ()))
。问题是:我们怎样才能从那里得到一个 m (Either B A)
?
让我们忘记 m
,因为它并不重要。我们想要一个函数:
awesomeFunction :: Either B (Either A ()) -> Either B A
类型 Either B (Either A ())
的值可以是 Left b
、Right (Left a)
或 Right (Right ())
,这意味着您可以有一个 A
、一个 B
或者什么都没有。
Either B A
类型的值可以是 Left b
或 Right a
。让我们尝试实现 awesomeFunction
.
awesomeFunction (Left b) = Left b
awesomeFunction (Right (Left a)) = Right a
awesomeFunction (Right (Right ()) = ???
在我们什么都没有的情况下(一个Right (Right ()
),我们不能凭空创建一个A
,所以不可能创建这个函数。
OP 在评论中澄清:
I have some value [x
] that is of type ExceptT B m ()
. That value may be either left or right. However, then I do forever x
and then it becomes left at some point (m
is StateT
) or it never terminates.
问题是您过早地将结果类型固定为 ()
。当你 运行 一个动作 forever
时,你会得到任何你想要的结果类型。特别是,您可以将左侧和右侧固定为同一类型,突然一切正常。也就是说,你可以这样写
either return return =<< runExceptT (forever x)
你最终会得到一个 returns 异常发生的动作。
是否可以创建具有以下签名的函数?
ExceptT A (ExceptT B m) () -> ExceptT B m A
我的想法是这样的,因为 x
是上述函数的参数(而且我很讨厌 monad,所以它很可能是错误的)。
runExceptT x :: ExceptT B m (Either A ())
但是后来我坚持得到像 Either A () -> A
这样的东西,它本质上必须考虑 Right
,因此要么失败,要么 return A
的某个常数(我没有)。
但是,我知道 x
的原始值恰好是左值之一,否则定义将无限循环。
简答:那不可能。
长答案:ExceptT e m a
包含一个 m (Either e a)
,因此 ExceptT A (ExceptT B m) ()
包含一个 ExceptT B m (Either A ())
,后者又包含一个 m (Either B (Either A ()))
。问题是:我们怎样才能从那里得到一个 m (Either B A)
?
让我们忘记 m
,因为它并不重要。我们想要一个函数:
awesomeFunction :: Either B (Either A ()) -> Either B A
类型 Either B (Either A ())
的值可以是 Left b
、Right (Left a)
或 Right (Right ())
,这意味着您可以有一个 A
、一个 B
或者什么都没有。
Either B A
类型的值可以是 Left b
或 Right a
。让我们尝试实现 awesomeFunction
.
awesomeFunction (Left b) = Left b
awesomeFunction (Right (Left a)) = Right a
awesomeFunction (Right (Right ()) = ???
在我们什么都没有的情况下(一个Right (Right ()
),我们不能凭空创建一个A
,所以不可能创建这个函数。
OP 在评论中澄清:
I have some value [
x
] that is of typeExceptT B m ()
. That value may be either left or right. However, then I doforever x
and then it becomes left at some point (m
isStateT
) or it never terminates.
问题是您过早地将结果类型固定为 ()
。当你 运行 一个动作 forever
时,你会得到任何你想要的结果类型。特别是,您可以将左侧和右侧固定为同一类型,突然一切正常。也就是说,你可以这样写
either return return =<< runExceptT (forever x)
你最终会得到一个 returns 异常发生的动作。