0

I'm experimenting with this in SML

- val p = (fn (x,y) => x + y, fn (x,y) => x - y)
val p = (fn,fn) : (int * int -> int) * (int * int -> int)

But I may only evaluate it one at a time

- #1(p)(3,2)
5

or

- #2(p)(3,2)
1

Why can I not do both?

- (p)(3,2)
Error: operator is not a function [tycon mismatch]...

What quasi-lambda calculus form would I need to have it return a 2-tuple, the first position from x+y lambda function, and the second from x-y lambda function? At first glance, that's what it looks like it will do. In general, I'm lost as to what a variable and a function is in this example.

147pm
  • 2,137
  • 18
  • 28

2 Answers2

2

I am not sure what you are asking. A function is a function, a pair is a pair. A pair of functions is not a function, so it cannot be applied.

However, you can convert a pair of functions into a function on pairs by defining a form of map function on pairs, similar to map for lists:

fun mapPair (f, g) (x, y) = (f x, g y)

With that, you can do:

mapPair (p) (2, 3)

Edit: The above is just shorthand for a curried function, i.e., a function returning a function:

fun mapPair (f, g) = fn (x, y) => (f x, g y)

or equivalently:

val mapPair = fn (f, g) => fn (x, y) => (f x, g y)
Andreas Rossberg
  • 34,518
  • 3
  • 61
  • 72
  • 1
    This `mapPair` function resembles the [`***`](https://hackage.haskell.org/package/base/docs/Control-Arrow.html#v:-42--42--42-) operator from Haskell's `Control.Arrow` library, concretized for tuples. It also resembles the [`bifmap`](https://hackage.haskell.org/package/bifunctors-5.5.7/docs/Data-Bifunctor-Functor.html) of `Data.Bifunctor`. I would think that the latter is a good abstraction in SML, too. – sshine Mar 25 '20 at 15:07
  • Having two separate sets of arguments, `(f, g)` and `(x, y)` for `mapPair` is new to this beginner. In the application I intuit the `p` is taken by the `(f, g)` and the `(2, 3)` by the `(x, y)`. That's quite magical! Could you point me to other examples or a tutorial treatment of this? As I've alluded, this looks similar to lambda calculus and its reduction, but I'm not sure how. Need to get through my Greg Michaelson book. So could this be written in lambda calculus? – 147pm Mar 25 '20 at 21:18
  • @147pm, nothing magical, just shorthand syntax for a curried function, i.e., a lambda returning a lambda. See my edit. Yes, ML is nothing but an enriched lambda-calculus. – Andreas Rossberg Mar 26 '20 at 05:53
2

fn (x,y) => x + y and fn (x,y) => x - y are functions; p is a pair of functions; #1 p and #2 p are functions; a pair is not a function.

If you want an anonymous function (I'm assuming that's what "quasi-lambda calculus form" means), it would look like this

fn (f, g) => fn x => (f x, g x)

that is, first take a pair of functions, then something, then apply both functions to the something.

- (fn (f,g) => fn x => (f x, g x)) p (3,2);
val it = (5,1) : int * int

or, if you're determined on using selectors instead of pattern matching:

- (fn fns => fn x => (#1 fns x, #2 fns x)) p (3,2);
val it = (5,1) : int * int
molbdnilo
  • 64,751
  • 3
  • 43
  • 82