Haskell unwrap 也许保持多态性

Haskell unwrap Maybe keep polymorphism

Haskell又是初学者。如果我想打开一个 Maybe 类型并保持抽象,我会使用:

fUnwrap :: Maybe a -> a 
fUnwrap (Just n) = n 
fUnwrap Nothing = ???

无论我用 Nothing 做什么,编译器总是唠叨要更具体地处理 Nothing...你们能帮帮我吗?

这是合乎逻辑的。编译器会导出一个 a 类型的值,但是这里您无法提供任何值,因为 a 可以是任何东西(BoolInt[Int], Maybe Int, 等等).

这与其说是一个编程问题,不如说是一个设计问题:如果是Nothing,你想做什么?这里有一些选项:

  1. 提供一个默认值,那么签名就是:

    fUnwrap :: <b>a -></b> Maybe a -> a 
    fUnwrap <b>_</b> (Just n) = n
    fUnwrap <b>d</b> Nothing = <b>d</b>
    
  2. 如果是 Nothing 我们会抛出一个错误(我们可以这样做,既可以省略该行,也可以显式地抛出一个错误,尽管在后一种情况下我们可以指定一个原因):

    fUnwrap :: Maybe a -> a
    fUnwrap (Just n) = n
    fUnwrap Nothing = <b>error "Nothing has no value"</b>
    
  3. 我们returnundefined:

    fUnwrap :: Maybe a -> a
    fUnwrap (Just n) = n
    fUnwrap Nothing = <b>undefined</b>
    

    undefined :: a 是一个在计算时会引发错误的对象。因此它是 error 的特例,但我们 "postpone" 评估使得如果该值不是必需的,我们不会得到错误。

但我个人认为第一种方法在这里是可取的,因为函数签名没有指定它们会引发错误,因此它会导致代码可能会失败,而没有提示它可以。

A Maybe a 通常用作可以 "fail" 的计算的结果类型:如果它成功,它 returns Just x (与 x 结果),否则 returns Nothing.

例如,您可以使用 do 符号从可能会失败的计算链中构造一个 Maybe a。例如:

foo :: Int -> Maybe Int
foo x = do
    y <- someComputation x
    otherComputation y

以这里为例 someComputation, otherComputation :: Int -> Maybe Int.

这是不可能的,因为你的函数已经写好了。由于该函数是纯函数,您不能 return a 因为您唯一的输入是 Nothing。

Maybe 的美妙之处在于您不需要"unwrap"它。您可以使用 fmap 函数仅在包装数据存在时对其进行操作,并且在 Nothing 情况下隐式不执行任何操作。