如何在 Haskell 中模式匹配中间值

vku*_*cki 2 haskell

题

在Bartosz Milewski 的《程序员分类理论》一书中,第 4.3 章。

您必须编写一个 Kleisli 范畴,其中态射是偏函数。这是我无法编译的尝试:

data Optional a = Valid a | Invalid deriving (Show)

return :: a -> Optional a
return x = Valid x

(>=>) :: (a -> Optional b) -> (b -> Optional c) -> (a -> Optional c)
f (>=>) g = \x ->
    let s = f x
    in | s == Valid v = g v
       | s == Invalid = Invalid
Run Code Online (Sandbox Code Playgroud)

在>=>运算符定义中,我想对中间值进行模式匹配s以测试是否为Valid(然后调用f)或是否为Invalid(然后返回Invalid)。我怎样才能做到这一点 ?

Dan*_*son 5

你可以case用来做模式匹配:

f >=> g = \x ->
  case f x of
    Valid v -> g v
    Invalid -> Invalid
Run Code Online (Sandbox Code Playgroud)

在您的问题中,您似乎还试图使用守卫进行模式匹配和绑定值。Haskell 不允许这样做。守卫只是一个布尔值表达式,它必须为真才能匹配前面的(有时是可选的)模式。Haskell 语言并没有真正“理解”(==)运算符的含义。它只是将其视为与其他任何功能一样的功能。并且确实可以为一种类型定义它,使其不对应于模式匹配所需的相同类型。

守卫可以使用来自模式(或更大范围)的变量,但不能像模式一样绑定新的变量。因此这将是错误的,因为v将是未定义的。

f >=> g = \x ->
  case f x of
    _ | x == Valid v -> g v
    _ | x == Invalid -> Invalid
Run Code Online (Sandbox Code Playgroud)

这也将使编译器基本上不可能知道您的模式是否详尽无遗(即没有任何情况下都不会匹配的值)