PureScript - 无法将 Maybe String 类型与 String 类型匹配

PureScript - Could not match type Maybe String with type String

以下 PureScript 代码尝试记录字符串数组中的单个值

module Main where

import Effect (Effect)
import Effect.Console (log)
import Prelude
import Data.Array

x :: Array String
x = ["Jason","Zack","Billy","Trini","Kimberly"]

y :: String
y = x !! 2

main ∷ Effect Unit
main = do
  log (y)

但是它会产生以下错误代码:

  Could not match type
  
    Maybe String
  
  with type
          
    String
          

while checking that type Maybe String
  is at least as general as type String

好像是这行代码

y = x !! 2

Returns 一个 Maybe String 而不是一个 String.

所以问题是,

  1. 如何将Maybe String类型转成String类型(过程中提供默认值)

  2. 是否有任何其他方法来访问 returns 一个字符串而不是可能字符串的数组(在本例中为字符串数组)?

要将 Maybe a 转换为 a 以在过程中提供默认值,请使用 fromMaybe:

y :: String
y = x !! 2 # fromMaybe ""

专业提示:如果您正在寻找特定形状的函数,您可以通过函数签名搜索 Pursuit。例如,如果您对泛型感到不舒服,您可能已经通过 searching for a -> Maybe a -> a. Or even more specifically search for String -> Maybe String -> String 发现了 fromMaybe(尽管诚然,在这种情况下,fromMaybe 在页面上显得有点低)。


如果您正在寻找“任何其他方式”来访问数组并获得 String,您必须问问自己:当数组少于三个元素时会发生什么?如果你要求数组中的第三个字符串,但它只包含两个,结果应该是什么?

显然没有理智的答案,这就是为什么 index 函数 returns a Maybe.

另一种选择(FP 语言通常倾向于避免)是在这种情况下导致灾难性的运行时错误。这样的功能将被称为“部分”功能,这意味着它仅适用于 一些 输入而不适用于 所有可能的 输入。图书馆确实提供 some partial functions on arrays in Data.Array.Partial,但 index 不是其中之一。我的猜测是,从来没有人需要它。

如果你真的想要,你可以自己制作:

unsafeIndex :: forall a. Array a -> Int -> a
unsafeIndex arr idx =
  unsafePartial
    case arr !! idx of
      Just a -> a

这里我使用的 case 表达式不包含所有可能性(即没有 Nothing 情况),这通常会导致编译错误,但后来我使用 magic unsafePartial function 摆脱它(或者更确切地说,将其推迟到运行时)。在运行时,如果给定无效索引,此函数将崩溃并提示“模式匹配失败”。

或者,我可以处理 Nothing 情况,但明确地崩溃而不是返回值。这样我就可以提供自定义错误消息:

unsafeIndex :: forall a. Array a -> Int -> a
unsafeIndex arr idx =
  case arr !! idx of
    Just a -> a
    Nothing -> unsafeCrashWith "Array is too short"

总而言之,我想重申,即使可以使用这样的偏函数,您还是应该尽可能避免使用它们。类型系统的存在是为了 帮助 你,而不是阻碍你,如果你选择绕过它,你就是搬起石头砸自己的脚。