在 Haskell 中组合任何类型的绑定

Posted

技术标签:

【中文标题】在 Haskell 中组合任何类型的绑定【英文标题】:Combining bindings for Either type in Haskell 【发布时间】:2020-11-23 16:32:02 【问题描述】:

对于以下代码,是否可以在 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 表现如何?你为什么要这个?你要求什么功能?你问“这可能吗?”但我很不清楚“this”是什么意思。 我想知道我是否可以创建一个可以导致两个选项之一的单个绑定。我只是想知道这是否有可能。我认为答案是否定的,但我是 Haskell 的新手,所以只想仔细检查 【参考方案1】:

表示不确定值的一种常用技术是生成一个列表,其中每个可能性都有一个元素。例如,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(&lt;$&gt;) 将确定性计算转换为了解如何对非确定性值进行运算的计算。例如,如果你有

soCertain :: Either () () -> Int

那么你可以写其中一个(它们的意思相同):

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

【讨论】:

哇,谢谢你。这对我的理解很有帮助【参考方案2】:

没有。 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 () ()

【讨论】:

以上是关于在 Haskell 中组合任何类型的绑定的主要内容,如果未能解决你的问题,请参考以下文章

工具rest:Haskell的REST开源框架

Haskell 中的单子——洪峰老师讲创客道(三十五)

安全执行不受信任的 Haskell 代码

FFI 可以处理数组吗?如果是这样,怎么做?

在 Haskell 中构建组合自参照透镜

Haskell中两个列表元素的所有组合