当前位置: 首页 > 知识库问答 >
问题:

Haskell中的“Just”语法是什么意思?

令狐建修
2023-03-14

我在互联网上搜寻这个关键词的实际用途。我看过的每一篇Haskell教程都只是随机开始使用它,从来没有解释过它的功能(我看过很多)。

这是来自Real World Haskell的一段基本代码,它使用Just。我明白代码的作用,但我不明白Just的目的或功能是什么。

lend amount balance = let reserve    = 100
                      newBalance = balance - amount
                  in if balance < reserve
                     then Nothing
                     else Just newBalance

据我观察,它与也许打字有关,但这几乎是我所能学到的全部。

如果您能很好地解释一下的意思,我们将不胜感激。


共有3个答案

乐正宜人
2023-03-14

给定类型t,值Just t是类型t的现有值,其中表示未能达到某个值,或者表示具有某个值将毫无意义。

在您的示例中,负平衡是没有意义的,因此如果发生这种情况,它将被“无”所取代。

例如,这可以用于除法,定义一个除法函数,它取ab,如果b为非零,则只返回a/b,否则返回Nothing。它通常是这样使用的,作为异常的方便替代,或者像您前面的示例一样,用来替换没有意义的值。

壤驷向明
2023-03-14

目前的大多数答案都是对Just和朋友如何工作的高度技术性解释;我想我可以试着解释它的用途。

很多语言都有一个值,比如null,可以用来代替实际值,至少对于某些类型是这样。这让很多人非常愤怒,并被广泛认为是一个糟糕的举动。尽管如此,有时使用null这样的值来表示缺少某个东西还是很有用的。

Haskell解决了这个问题,它让你显式地标记出你可以拥有Nothing(其版本为null)。基本上,如果函数通常返回类型Foo,那么它应该返回类型,可能是Foo。如果要指示没有值,请返回Nothing。如果要返回一个值bar,则应该只返回bar

所以基本上,如果你不能什么都没有,你不需要,只要。如果你什么都没有,你只需要

也许没有什么神奇之处;它是建立在哈斯克尔式系统上的。这意味着您可以使用所有常用的Haskell模式匹配技巧。

湛钊
2023-03-14

它实际上只是一个普通的数据构造函数,恰好是在Prelude中定义的,它是自动导入到每个模块中的标准库。

定义如下所示:

data Maybe a = Just a
             | Nothing

该声明定义了一个类型,可能是a,它由一个类型变量a参数化,这意味着您可以将它与任何类型一起使用来代替a

该类型有两个构造函数,只有一个没有。当一个类型有多个构造函数时,这意味着该类型的一个值必须仅由一个可能的构造函数构造。对于这种类型,值要么通过Just构造,要么通过Nothing构造,没有其他(非错误)可能性。

由于没什么没有参数类型,当它用作构造函数时,它会命名一个常量值,该值是类型的成员,对于所有类型a。但是Just构造函数确实有一个类型参数,这意味着当用作构造函数时,它的行为就像一个从a类型到也许是的函数,即它具有a-类型

因此,一个类型的构造函数构建一个该类型的值;另一方面,当你想使用这个值时,模式匹配就发挥了作用。与函数不同,构造函数可以在模式绑定表达式中使用,这是对属于多个构造函数类型的值进行案例分析的方式。

为了在模式匹配中使用值,您需要为每个构造函数提供一个模式,如下所示:

case maybeVal of
    Nothing   -> "There is nothing!"
    Just val  -> "There is a value, and it is " ++ (show val)

在这种情况下,如果值是没什么,则第一个模式将匹配,如果值是使用Just构造的,则第二个模式将匹配。如果第二个匹配,它还将名称val绑定到构造您匹配的值时传递给Just构造函数的参数。

也许你已经熟悉了它的工作原理;也许值并没有什么魔力,它只是一种普通的哈斯克尔代数数据类型(ADT)。但它被大量使用,因为它有效地“提升”或扩展了一个类型,比如示例中的Integer,进入一个新的上下文,在这个上下文中,它有一个额外的值(Nothing),表示缺少值!然后,类型系统要求您在获取可能存在的整数之前检查该额外值。这可以防止大量的错误。

今天,许多语言通过NULL引用来处理这种“无值”值。著名的计算机科学家托尼·霍尔(Tony Hoare)承认这是他的“十亿美元错误”。也许类型不是解决这个问题的唯一方法,但它已被证明是一种有效的方法。

将一种类型转换为另一种类型,以便对旧类型的操作也可以转换为对新类型的操作,这是Haskell类型类背后的概念,称为Functor,它可能有一个的有用实例。

Functor提供了一个名为fmap的方法,它将范围超过基本类型(例如Intger)的值的函数映射到范围超过提升类型的值的函数(例如也许整数)。使用fmap转换以处理也许值的函数如下所示:

case maybeVal of
  Nothing  -> Nothing         -- there is nothing, so just return Nothing
  Just val -> Just (f val)    -- there is a value, so apply the function to it

所以如果你有一个可能是整数mux和一个Int-

我不确定你对aMonad的概念有多熟悉,但至少你以前使用过ioa,而且类型签名ioa看起来非常类似于可能是a。虽然IO的特殊之处在于它不会向您公开其构造函数,因此只能由Haskell运行时系统“运行”,但除了作为单子之外,它还是一个函子。事实上,单子只是一种特殊的函子,有一些额外的特性,这是一个重要的意义,但这里不是讨论这个问题的地方。

无论如何,像IO这样的Monad会将类型映射为表示“计算结果值”的新类型,您可以通过一个名为liftM的类似fmap的函数将函数提升为Monad类型,该函数将常规函数转化为“计算结果是通过计算函数得到的值”

您可能已经猜到(如果您已经读到这里)也许也是一个Monad。它表示“可能无法返回值的计算”。就像fmap示例一样,这让您可以进行一大堆计算,而无需在每一步后显式检查错误。事实上,Monad实例的构造方式,对也许值的计算会在遇到时立即停止,因此它有点像计算过程中的立即中止或无价值返回。

就像我之前说过的,在语言语法或运行时系统中烘焙的也许类型没有任何固有的东西。如果Haskell默认不提供它,您可以自己提供它的所有功能!事实上,无论如何,您都可以自己重新编写它,使用不同的名称,并获得相同的功能。

希望您现在能理解类型及其构造函数,但是如果还有什么不清楚的地方,请告诉我!

 类似资料:
  • 问题内容: 我已经和Lombok一起使用并积极使用了2个月。使用Java时,我会更加熟悉。但是,我第一次遇到了该语言的以下语法结构: 这是什么意思,如何编译? 问题答案: 这是一种实验性的Lombok语法,其创建目的是在引用多个注释时支持间接层,而不是使用。 语法有点奇怪;要使用这3种功能中的任何一种,您必须在中包装要应用于构造函数/方法/参数的注释。要应用多个注释,请使用。注释本身显然也可以具有

  • 问题内容: 我使用PHP已有很长时间了,但是我看到的类似, 确切地说,我在PHP Mongo页面中看到了这一点: 那么,该怎么办?这是相当难与谷歌或像字符PHP文件中进行搜索,和。 问题答案: (美元大括号)被称为 复杂(卷曲)语法 : 之所以称其为“复杂”,是因为语法复杂,而是因为它允许使用复杂的表达式。 可以通过此语法包括具有字符串表示形式的任何标量变量,数组元素或对象属性。只需以与出现在字符

  • 问题内容: 我遇到了以下我不认识的Java语法。 这部分很好: 但是,我没有得到: 这是什么? 问题答案: 这提供了该类的内联(匿名)子类。 从功能上讲,它与: 和 但是由于该类定义不在方法主体之外使用,因此可以将其定义为匿名。

  • 在以下代码示例中,来自颤振文档:

  • 我在这个Config::INI Perl中找到了一个tilde 我正在处理的文本中没有波浪号。我知道很重要,因为省略、和中的任何或所有内容都会使语法与我的文本不再匹配。 因为我知道我匹配的模式是什么,所以我改变了它,使方括号位于文本表达式周围,因此: 所以在我看来,实际上是说在这里匹配一个方括号,然后期待最后一个括号。 无论如何,我知道在正常的Perl中 不管怎样,我在留档中搜索了语法和正则表达式

  • 问题内容: 我正在寻找有关Google Go语言的信息。在“ A Go of Go”中,他们具有以下代码: 但是什么和 意味着什么呢? 您可以在http://tour.golang.org/#14上查看所有代码 问题答案: 它们是按位移位运算符。表示 x ×2 y ,而表示 x ×2 -y 或等效地x÷2 y。这些运算符通常用于操作值的二进制表示形式,就像十进制的10的幂一样,乘或除以2的幂分别具