在 Haskell 中组合 Either 类型的绑定

Combining bindings for Either type in Haskell

对于下面的代码,是否可以在Haskell中组合绑定?原代码如下:

Either1 a b = Left1 a | Right1 b

either1 :: Either1 () ()
either1 = Left1 ()

either2 :: Either1 () ()
either2 = Right1 ()

我想要的是这样的:

Either1 a b = Left1 a | Right1 b

either1 :: Either1 () ()
either1 = Left1 () || Right1 ()

这可能吗?如果是这样,如何才能正确完成?上面对预期类型大喊大叫。

我想知道我是否可以创建一个可以导致两个选项之一的绑定。我只想知道这是否可行。

没有。 Either1 () () 类型的东西可以是 Left1 ()Right1 (),但它仍然是一个单一的特定值。


请注意 Either () ()Bool 同构。 Bool 值是 TrueFalse,而不是两者的无限叠加。

to_bool :: Either () () -> Bool
to_bool (Left ()) = False
to_bool (Right ()) = True

from_bool :: Bool -> Either () ()
from_bool True = Right ()
from_bool False = Left ()

-- I leave it as an exercise to prove that
--  * to_bool . from_bool == id :: Bool -> Bool
--  * from_bool . to_bool == id :: Either () () -> Either () ()

表示不确定值的一种常用技术是生成一个列表,其中每种可能性都有一个元素。例如,Left ()Right () 之间的非确定性选择可以这样写:

whoKnows :: [Either () ()] -- read as: nondeterministic choice between multiple
                           -- possible values, each of type Either () ()
whoKnows = [Left (), Right ()]

稍后,当您想对这个不确定的值进行计算时,可以使用列表的 Monad 接口。例如,假设您有一个非确定性计算:

couldBeAnything :: Either () () -> [Int] -- read as: nondeterministic function
                                         -- that takes an Either () () and
                                         -- returns an Int
-- implementation left as an exercise for the reader

您可以像这样将两者结合起来:

soManyPossibilities :: [Int] -- read as: nondeterministic choice between multiple
                             -- possible values, each of type Int                
soManyPossibilities = do
    leftOrRight <- whoKnows
    couldBeAnything leftOrRight

您还可以将确定性计算转换为了解如何使用 pure(<$>) 对非确定性值进行运算的计算。例如,如果您有

soCertain :: Either () () -> Int

那么你可以写一个这样的(它们的意思是一样的):

fewerOptionsThisTimeMaybe :: [Int]
fewerOptionsThisTimeMaybe = do
    leftOrRight <- whoKnows
    pure (soCertain leftOrRight)
-- OR
fewerOptionsThisTimeMaybe = soCertain <$> whoKnows