Haskell中"Just"语法意味着什么?

ree*_*eem 109 syntax haskell

我已经在网上搜索了这个关键字的实际解释.我看过的每个Haskell教程都是随机开始使用它,而不是解释它的作用(我看过很多).

这是Real World Haskell使用的基本代码Just.我理解代码的作用,但我不明白它的目的或功能Just是什么.

lend amount balance = let reserve    = 100
                      newBalance = balance - amount
                  in if balance < reserve
                     then Nothing
                     else Just newBalance
Run Code Online (Sandbox Code Playgroud)

从我所观察到的,它与Maybe打字有关,但这几乎是我所学到的.

Just非常感谢对什么方法的一个很好的解释.

Lev*_*son 197

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

结构上可能是什么

定义看起来像这样:

data Maybe a = Just a
             | Nothing
Run Code Online (Sandbox Code Playgroud)

该声明定义了一个类型,Maybe a它由一个类型变量参数化a,这意味着你可以用任何类型代替它a.

建构与毁灭

该类型有两个构造函数,Just aNothing.当一个类型有多个构造函数时,这意味着必须仅使用一个可能的构造函数构造该类型的值.对于这种类型,值是通过Just或构造的Nothing,没有其他(非错误)可能性.

由于Nothing没有参数类型,当它用作构造函数时,它命名一个常量值,该值是Maybe a所有类型的类型成员a.但Just构造函数确实有一个类型参数,这意味着当用作构造函数时,它就像一个函数从类型aMaybe a,即它具有类型a -> Maybe a

因此,类型的构造函数构建该类型的值; 事情的另一面是你想要使用那个值,那就是模式匹配的用武之地.与函数不同,构造函数可用于模式绑定表达式,这是您可以对属于具有多个构造函数的类型的值进行大小写分析的方法.

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

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

在该情况表达式中,如果值为,则第一个模式将匹配Nothing,如果使用该值构造,则第二个模式将匹配Just.如果第二个匹配,它还会将名称绑定val到在Just构造匹配的值时传递给构造函数的参数.

可能意味着什么

也许你已经熟悉它是如何工作的; 它没有真正的Maybe价值观,它只是一个普通的Haskell代数数据类型(ADT).但是它使用了很多,因为它有效地"提升"或扩展了一个类型,例如Integer从你的例子中扩展到一个新的上下文,在这个上下文中它有一个额外的值(Nothing)代表缺乏价值!那么该类型的系统要求您检查额外的价值之前,它会让你在Integer可能是在那里.这可以防止大量的错误.

今天,许多语言通过NULL引用处理这种"无值"值.Tony Hoare是一位杰出的计算机科学家(他发明了Quicksort,并且是图灵奖获得者),他将此视为"十亿美元的错误".Maybe类型不是修复此问题的唯一方法,但事实证明它是一种有效的方法.

也许作为一个Functor

将一种类型转换为另一种类型的想法使得旧类型上的操作可以转换为对新类型起作用是Haskell类型类背后的概念Functor,它Maybe a具有一个有用的实例.

Functor提供了一个名为的方法fmap,它将范围超出基本类型(例如Integer)的值的函数映射到范围超过提升类型(例如Maybe Integer)的值的函数.转换fmap为处理Maybe值的函数如下所示:

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
Run Code Online (Sandbox Code Playgroud)

因此,如果你有一个Maybe Integerm_x和一个Int -> Int函数f,你可以直接fmap f m_x将函数应用f到它Maybe Integer而不用担心它是否真的有值.实际上,您可以将一整套提升Integer -> Integer函数应用于Maybe Integer值,并且只需要担心Nothing在完成时显式检查一次.

也许作为Monad

我不确定你对a的概念有多熟悉Monad,但你至少IO a在之前使用过,而且类型签名IO a看起来非常相似Maybe a.虽然IO它的特殊之处在于它不会向你展示它的构造函数,因此只能由Haskell运行时系统"运行",它仍然Functor是一个Monad.事实上,有一个重要的意义,即a Monad只是一种特殊的Functor有一些额外的功能,但这不是进入它的地方.

无论如何,Monads喜欢将IO地图类型表示为表示"产生值的计算"的新类型,并且您可以Monad通过一个非常类似fmap的函数将函数提升为类型,该函数 liftM将常规函数转换为"计算结果,通过评估得到的值功能."

你可能已经猜到了(如果你已经读过这篇文章)那Maybe也是一个Monad.它表示"可能无法返回值的计算".与fmap示例一样,这使您可以执行一大堆计算,而无需在每个步骤后显式检查错误.事实上,Monad构造实例的方式,一旦遇到a,Maybe值的计算就会停止Nothing,因此它有点像在计算过程中立即中止或无值返回.

你可能写的也许吧

就像我之前说的那样,Maybe语言语法或运行时系统中没有任何固有的类型.如果Haskell默认不提供它,您可以自己提供所有功能!实际上,无论如何,您可以自己再次编写它,使用不同的名称,并获得相同的功能.

希望您Maybe现在了解其类型及其构造函数,但如果仍有任何不清楚的地方,请告诉我们!

  • 多么出色的答案!应该提到的是,Haskell经常使用`Maybe`,其他语言将使用`null`或`nil`(在每个角落都潜伏着令人讨厌的`NullPointerException).现在其他语言也开始使用这个结构:Scala作为`Option`,甚至Java 8也会有`Optional`类型. (15认同)
  • 这是一个很好的解释.我读过的许多解释都暗示Just是Maybe类型的构造函数,但没有一个真正明确. (3认同)
  • @Landei 自 70 年代的 ML 以来,选项类型就已经存在,Scala 更有可能从那里继承它,因为 Scala 使用 ML 的命名约定,带有构造函数的 Option 和 none。 (2认同)

Bre*_*don 37

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

许多语言具有类似的值null,可以使用而不是实际值,至少对于某些类型.这让很多人非常生气,被广泛认为是一个不好的举动.尽管如此,有时候有一个值null可以表明没有东西.

Haskell通过明确标记可以拥有Nothing(其版本为a null)的位置来解决此问题.基本上,如果你的函数通常会返回类型Foo,那么它应该返回类型Maybe Foo.如果您想表明没有价值,请返回Nothing.如果要返回值bar,则应返回Just bar.

所以基本上,如果你不能拥有Nothing,你就不需要了Just.如果你有Nothing,你需要Just.

没有什么神奇之处Maybe; 它建立在Haskell类型系统上.这意味着您可以使用所有常用的Haskell 模式匹配技巧.

  • 为什么语言设计需要一个Just而不是简单的把返回值不带关键字。我 (2认同)

qap*_*hla 13

给定一个类型t,值Just t是类型的现有值t,其中Nothing表示无法达到值,或者具有值无意义的情况.

在你的例子中,负平衡是没有意义的,所以如果发生这样的事情,它将被替换为Nothing.

再举一个例子,这可以用于除法,定义一个取a和的除法函数,如果非零则b返回,否则返回.它通常像这样使用,作为异常的替代方法,或者像前面的例子一样,替换没有意义的值.Just a/bbNothing

  • 如果你删除了`Just`,你的代码就不会出现问题."Just"的原因是保持适当的类型.有一种类型(实际上是一个monad,但它更容易被认为是一种类型)`也许是t`,它由"Just t"和"Nothing"形式的元素组成.由于`Nothing`具有类型`Maybe t`,因此无法正确键入可以计算为"Nothing"或某些类型为"t"的值的表达式.如果某个函数在某些情况下返回"Nothing",那么使用该函数的任何表达式都必须有某种方法来检查它(`isJust`或case语句),以便处理所有可能的情况. (7认同)
  • @qaphla:你对它是一个"monad,实际上,[...]"的评论是误导性的.`也许t` _is_只是一种类型.事实上,`Maybe`的`Monad`实例不会将其转换为非类型的东西. (3认同)
  • 那么假设在上面的代码中我删除了 Just,为什么这不起作用呢?你是否必须在任何时候你想要什么都没有?如果表达式内的函数不返回任何内容,那么该表达式会发生什么情况? (2认同)
  • 所以Just只是在Maybe类型中保持一致,因为常规t不在Maybe类型中.现在一切都更清楚了.谢谢! (2认同)