[Haskell-cafe] Does Haskell have this SML syntax?

Viktor Dukhovni ietf-dane at dukhovni.org
Fri Mar 26 21:03:30 UTC 2021


On Fri, Mar 26, 2021 at 03:01:03PM -0500, Galaxy Being wrote:

> Now, what might be the purpose of this \ case?

It is just a short-hand:

    \ case
        pat1 -> e1
        pat2 -> e2
        ...

is identical to:

    \ x -> case x of
        pat1 -> e1
        pat2 -> e2
        ...

In other words, a concise function taking a single argument that is
immediately the verbatim subject of some pattern matches.

    maybe fallback extract = \ case
        Just av -> extract av
        Nothing -> fallback

> In SML the code I gave simply looks like a trick to simulate a curry
> where the function takes a parameter, then morphs into a new function
> that takes the next parameter.

This is not a trick, it is elementary mathematical logic,
In set theory, we have an isomorphism:

    A x B -> C      <---> A -> (B -> C)

this was eventually formalised in Churches Lambda Calculus.

    λ(x,y). mumble  <--->  λx. (λy. mumble)
    -- mumble = ..., some formula in x and y

> What would be the main use of this \ case ploy? I can't believe it was
> dreamt up just to fake currying.

I don't understand why you're using words like "fake" and "ploy".  This
is just a shorthand that avoids having to introduce a superfluous
intermediate variable that adds nothing to the clarity of the code.

> What's still strange to me is how the system knows to reach past the
> pred

That's just the same isomorphism, for fixed pred, (subst_c pred) is a
function of (a, MyList a).  But we can also view the same subst_c as a
function of two arguments (pred, (a, MyList a)).  The two viewpoints are
isomorphic.  The notation for anonymous functions allows us to avoid
having to name the restriction of `subst_c` to a given value of `pred`.

        subst_c pred = \ (a, MyList a) -> mumble
  <---> subst_c pred (a, MyList a) = mumble

> data MyList a = Empty | Cons a (MyList a) deriving (Eq, Ord, Show)
> subst_c :: (a -> Bool) -> (a, MyList a) -> MyList a
> subst_c pred = \ case
>                      (_, Empty)    -> Empty
>                      (n, Cons e t)
>                        | pred e    -> Cons n $ subst_c pred (n, t)
>                        | otherwise -> Cons e $ subst_c pred (n, t)
> 
> and pattern match on the (a, MyList a) inside the function.

Well "closures" that capture a context, are immensely useful in writing
reusable software building blocks.  You can e.g. name "subst_c pred"
specialised for a particular predicate and use it repeatedly, or pass
it as a function to be used in some higher-order function.

> So again, how can it do this and why would I want to?

When working with higher-order functions, the function-valued arguments
passed to them are often partially-applied general-purpose "combinators".

Functional programming would be much more tediously verbose, if we
couldn't write function-valued expressions by partially applying
existing functions.  Instead of:

    map (* 2) [1,2,3,4]

we'd have to always write:

    map double [1,2,3,4]
      where
        double x = 2 * x

or similar.  Often the expression is at least as clear as any name
you might give it.

-- 
    Viktor.


More information about the Haskell-Cafe mailing list