unison/unison-src/transcripts/lambdacase.md
2024-06-25 11:11:07 -07:00

2.5 KiB

Lambda case syntax

scratch/main> builtins.merge

This function takes a single argument and immediately pattern matches on it. As we'll see below, it can be written using cases syntax:

isEmpty x = match x with
  [] -> true
  _ -> false
scratch/main> add

Here's the same function written using cases syntax:

isEmpty2 = cases
  [] -> true
  _ -> false

Notice that Unison detects this as an alias of isEmpty, and if we view isEmpty

scratch/main> view isEmpty

it shows the definition using cases syntax opportunistically, even though the code was originally written without that syntax.

Multi-argument cases

Functions that take multiple arguments and immediately match on a tuple of arguments can also be rewritten to use cases. Here's a version using regular match syntax on a tuple:

merge : [a] -> [a] -> [a]
merge xs ys = match (xs, ys) with
  ([], ys) -> ys
  (xs, []) -> xs
  (h +: t, h2 +: t2) ->
    if h <= h2 then h  +: merge t (h2 +: t2)
    else            h2 +: merge (h +: t) t2
scratch/main> add

And here's a version using cases. The patterns are separated by commas:

merge2 : [a] -> [a] -> [a]
merge2 = cases
  [], ys -> ys
  xs, [] -> xs
  h +: t, h2 +: t2 ->
    if h <= h2 then h  +: merge2 t (h2 +: t2)
    else            h2 +: merge2 (h +: t) t2

Notice that Unison detects this as an alias of merge, and if we view merge

scratch/main> view merge

it again shows the definition using the multi-argument cases syntax opportunistically, even though the code was originally written without that syntax.

Here's another example:

structural type B = T | F

blah : B -> B -> Text
blah = cases
  T, x -> "hi"
  x, y -> "bye"

blorf = cases
  x, T -> x
  x, y -> y

> blah T F
> blah F F
> blorf T F

Patterns with multiple guards

merge3 : [a] -> [a] -> [a]
merge3 = cases
  [], ys -> ys
  xs, [] -> xs
  h +: t, h2 +: t2 | h <= h2   -> h  +: merge3 t (h2 +: t2)
                   | otherwise -> h2 +: merge3 (h +: t) t2
scratch/main> add
scratch/main> view merge3

This is the same definition written with multiple patterns and not using the cases syntax; notice it is considered an alias of merge3 above.

merge4 : [a] -> [a] -> [a]
merge4 a b = match (a,b) with
  [], ys -> ys
  xs, [] -> xs
  h +: t, h2 +: t2 | h <= h2   -> h  +: merge4 t (h2 +: t2)
  h +: t, h2 +: t2 | otherwise -> h2 +: merge4 (h +: t) t2