How to pattern-match an intermediate value in Haskell

不想你离开。 提交于 2020-06-27 18:54:30

问题


Question

In the book Category Theory for Programmers by Bartosz Milewski, chapter 4.3.

You must code a Kleisli category where morphisms are partial functions. Here is my attempt which does not compile:

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

In the >=> operator definition, I want to pattern-match the intermediate value s to test if is Valid (and then call f) or if it is Invalid (and then return Invalid). How can I do this ?


回答1:


You can use case to do pattern matching:

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

In your question you also seem to be trying to use guards for pattern matching and binding values. Haskell does not allow this. A guard is just a boolean valued expression which must be true for the preceding (sometimes optional) pattern to match. Haskell the language doesn’t really “understand” the (==) operator as meaning equality. It just sees it as a function like any other. And indeed one can define it for a type to not correspond to the same kind of equality that a pattern match requires.

A guard is allowed to use variables from the pattern (or from a larger scope) but can’t bind new ones like a pattern. Therefore this would be wrong because v would be undefined.

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

It would also make it basically impossible for the compiler to ever know if your patterns are exhaustive (ie that there are no values which wouldn’t be matched by any case)



来源:https://stackoverflow.com/questions/59226842/how-to-pattern-match-an-intermediate-value-in-haskell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!