【问题标题】:How to pattern-match an intermediate value in Haskell如何在 Haskell 中对中间值进行模式匹配
【发布时间】:2019-12-09 05:59:19
【问题描述】:

问题

在 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

>=> 运算符定义中,我想对中间值s 进行模式匹配以测试是Valid(然后调用f)还是Invalid(然后返回@ 987654327@)。我该怎么做?

【问题讨论】:

  • 我认为首先你应该考虑使 Optional 类型成为 Monad 类型类的实例,然后 Kleisli 组合运算符将免费提供f >=> g = \x -> f x >>= g
  • 我以后会尝试这个Redu,本书的重点是逐步学习如何应用类别理论。

标签: haskell


【解决方案1】:

您可以使用case 进行模式匹配:

f >=> g = \x ->
  case f x of
    Valid v -> g v
    Invalid -> Invalid

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

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

f >=> g = \x ->
  case f x of
    _ | x == Valid v -> g v
    _ | x == Invalid -> Invalid

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

【讨论】:

  • 在某种意义上,case 是 Haskell 中解构的基本工具,因为其他模式匹配脱糖成核心语言中的 case 语句。所以最好掌握它。
  • 好的,所以在将 case 应用于函数的参数的特定情况下,守卫是语法糖,对吧?
  • @vkubicki 我不明白你的意思。你觉得后卫是什么?你认为它是什么语法糖?
  • learnyouahaskell.com/syntax-in-functions 有个叫守卫的部分
  • 我以为守卫是用于模式匹配的,但似乎只用于对值进行测试。
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
相关资源
最近更新 更多