【问题标题】:What's the purpose of Just in Elm?Just in Elm 的目的是什么?
【发布时间】:2022-08-16 06:14:33
【问题描述】:

所以,我一直在 Exercism.org 上做 Elm 跟踪,我刚刚完成了关于 Maybe 概念的练习,但有一件事我还不清楚。 Maybe的定义中Just的用途是什么?

type Maybe a = Nothing | Just a

例如,IntJust Int 之间有什么区别,如果我之前不添加Just 字,为什么整数不被视为Just Int

更具体地说,当我试图解决 RPG problem 时,我的第一次尝试导致了这样的结果:

type alias Player =
    { name : Maybe String
    , level : Int
    , health : Int
    , mana : Maybe Int
    }

revive : Player -> Maybe Player
revive player =
    case player.health of
        0 ->
            if player.level >= 10 then
                Player player.name player.level 100 100
            else
                Player player.name player.level 100 Nothing
        _ ->
            Nothing

只是为了发现我的错误出现在 if 语句中,它应该返回 Just Person,即:

            if player.level >= 10 then
                Just (Player player.name player.level 100 (Just 100))
            else
                Just (Player player.name player.level 100 Nothing)

    标签: functional-programming elm


    【解决方案1】:

    如果您来自 Python 等动态类型的背景,那么很容易认为它毫无意义。在 Python 中,如果您有一个参数并且希望它是整数或空的,则传递整数或 None。而每个人都明白None 是没有整数。

    即使您来自一个做得不好的静态类型语言,您仍然可能认为它很奇怪。在 Java 中,每一个引用数据类型可以为空,所以String 真的是“嗯,这里可能有也可能没有String”,而MyCustomClass 真的是“嗯,这里可能真的有也可能没有实例”。一切可以是null,这导致每个人都在不断地检查事情是否是null

    广义上讲,这个问题有两种解决方案:可空类型和可选类型。在像 Kotlin 这样具有可空类型的语言中,Int 是整数类型。 Int可以只要包含整数。不是null,不是字符串,不是其他任何东西。但是,如果你要允许 null,请使用类型 Int?Int? 类型要么是整数,要么是 null 值,除非你先检查 null,否则你不能用它做任何类似整数的事情(例如将它添加到另一个整数)。这是null 问题最直接的解决方案,适用于来自Java 之类的语言的人。在那个类比中,Int 确实是Int? 的子类型,所以每个整数都是Int? 的一个实例。 3IntInt? 的一个实例,它表示“这是一个整数”和“这是一个可选但存在的整数”。

    这种方法在带有子类型的语言中效果很好。如果您的语言是从典型的 OOP 层次结构构建的,那么很容易说“好吧,T 显然是T? 的子类型”并继续前进。但 Elm 不是这样建造的。 Elm 中没有子类型关系(有统一,这是另一回事)。 Elm 基于 Haskell,它是从 Hindley-Milner model 构建的。在这个模型中,每个值都有一个唯一的类型。

    而在 Kotlin 中,3IntInt?NumberNumber? 的一个实例,以此类推一直到 Any?(Kotlin 中的顶级类型) ),Elm 中没有等价物。没有一切都继承自的“顶级类型”,也没有子类型。所以说3是多种类型的实例是没有意义的。在 Elm 中,3Int 的一个实例。故事结局。而已。如果函数接受Int 类型的参数,它必须是一个整数。由于3 不能是其他类型的实例,我们需要另一种方式来表示“可能存在或不存在的整数”。

    type Maybe a = Nothing | Just a
    

    输入可选类型。 3 不能是可选整数,因为它是 Int,仅此而已。但是另一方面,Just 3...Just 3 是一个完全不同的值,并且它是类型是Maybe IntJust 3只要在需要可选整数的情况下有效,因为它不是IntMaybe a 就是所谓的可选类型;它是一个完全独立的类型,代表类型a,但可选。它的用途和T? 使用 Kotlin 之类的语言相同,但它是建立在不同的基础之上的。

    进入哪个更好会破坏这篇文章,我认为这在这里并不重要。我有我的意见,但其他人也有他们的。可选类型和可空类型是处理可能存在或不存在的值的两种不同方法。 Elm(和类似 Haskell 的语言)使用一种,而其他语言可能使用另一种。一个全面的程序员应该对两者都感到满意。

    【讨论】:

    • 很好的答案! "进入哪个更好……” - 不过,我现在很好奇。有什么东西比另一个更容易(!)吗?是否有任何语义不同的习语(或边缘情况)?
    • 哇,有道理!现在将这两种分开似乎更合乎逻辑。非常感谢您的精彩回答。
    • @Bergi 对我来说,主要因素是可选类型组合得更好。也就是说,Maybe (Maybe a) 是与Maybe a 不同的类型(NothingJust Nothing 是可区分的),而(T?)? 等价于T?,并且只有一个null。当使用泛型可能或可能尚未为空的情况下使用泛型时,这可能会咬你一口。不是一个大问题,但这就是为什么我个人更喜欢Maybe 而不是可空类型。另一方面,能够将Int 隐式向上转换为Int? 对人体工程学和代码可读性有好处,因此双方都有自己的拥护者。
    【解决方案2】:

    如果我之前不添加Just 字,为什么整数不被视为Just Int

    仅仅是因为没有构造函数 (Just),它只是一个整数,而不是其他东西。没有自动类型转换,您必须明确说明您想要什么。如果您的意思是单元素列表[100],您是否还会考虑允许编写100?很快,如果有人写了100,您将不知道这意味着什么。

    这不是特定于Maybe 及其Just 变体,这是所有数据类型的规则。 Maybes 也不例外,即使语言令人困惑 - Int 只是 Int,而不是 Just Int

    【讨论】:

      【解决方案3】:

      在 Elm 中只是一个标签,但在这种情况下,您可以将其视为一个函数,该函数接受 Int 类型的值,并返回 Maybe Int 类型的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多