Lambda the Ultimate

inactiveTopic Currying of Complex Interfaces
started 2/6/2004; 8:36:18 AM - last post 2/9/2004; 6:10:51 PM
andrew cooke - Currying of Complex Interfaces  blueArrow
2/6/2004; 8:36:18 AM (reads: 254, responses: 9)
Another question, more direct this time. What kind of support is available for currying complex interfaces in typed languages?

For example, maybe I have an interface (function?) that has parameters like:

  • input-frame
  • bias-correction
  • flat-field
  • apertrue-limits
  • exposure-time
and returns an output-frame.

One day I want to provide everything but input-frame and be left with something (a function, I guess) that converts input-frame to output-frame. Another day I want to specify all but bias-correction and flat-field, so that I have a function with type bias-correction -> flat-field -> output-frame (the order of the first two arguments is not important)

Obviously I can do this explicitly, but I'm thinking it might be automatic in some language with named function arguments, or perhaps some more exotic kind of support for interfaces.

Extra points if the language can be both compiled and interpreted.

(The application is a scripting language with "tasks" where many parameters are fixed over a series of images. Maybe there's a neater approach from another direction?)

Andrei Formiga - Re: Currying of Complex Interfaces  blueArrow
2/6/2004; 11:45:42 AM (reads: 243, responses: 1)
OCaml has some support for this since the introduction of labels in version 3. The arguments to a function are named using labels, and then labelled arguments can be omitted. The application of a function to an incomplete argument set will produce, as a value, a function which accepts the remaining arguments.

I don't have OCaml installed at work, and so I'll not risk giving a possibly wrong example. Maybe I'll do it later, if no one else does.

andrew cooke - Re: Currying of Complex Interfaces  blueArrow
2/6/2004; 12:40:05 PM (reads: 231, responses: 0)
thanks. ocaml was my best guess, but i didn't know for sure if it went the whole way (and scala demonstrated that some solutions are completely off my radar).

however, since then i've decided it would be nice to be able to examine the curried function to see what the parameter values are. since that seems unlikely for functions i'm now wondering whether i need to have a record that contains all the arguments for a task as something separate from the task itself, and apply one to the other using some kind of dsl glue. an approach like that feels as though it's edging towards objects (not that that's a problem, nor does it exclude ocaml).

or maybe these records are best considered as dictionaries, and i should be looking to lua or python. i'd like to use a language with hm type inference if possible, though (personal bigotry; this is unconnected with my previous largely java-based question).

Neel Krishnaswami - Re: Currying of Complex Interfaces  blueArrow
2/6/2004; 1:01:26 PM (reads: 222, responses: 1)
Hi Andrew,

Here's a snippet from the interface to a regexp library I'm writing in Ocaml:

    val fold :
      zero:'a ->
      empty:'a ->
      char:(char -> 'a) ->
      seq:('a * 'a -> 'a) ->
      alt:('a * 'a -> 'a) ->
      star:('a -> 'a) ->
        t -> 'a

As you can see, each case of the datatype gets a named argument. I can curry this more or less however I like, in whatever order. It also has optional arguments, but I haven't made much use of them.

andrew cooke - Re: Currying of Complex Interfaces  blueArrow
2/6/2004; 2:29:05 PM (reads: 211, responses: 0)

Darius Bacon - Re: Currying of Complex Interfaces  blueArrow
2/6/2004; 3:32:18 PM (reads: 210, responses: 0)
Here's an answer I have lying around for when you have positional arguments, though keyword arguments are probably more appropriate for your problem. It lets you fill in an arbitrary subset of the arguments at a time.

(defmacro cute (fn &rest args)
  "This is roughly like currying in Haskell.  Example:
(cute + <> 1) --> (let ((t1 1)) (lambda (<>) (+ <> t1)))
And CUTE really is the name they give this in the Scheme SRFI... ugh."
  (let ((vars (mapcar (lambda (a) (gensym)) args)))
    `(let ,(loop for a in args
                 for v in vars
                 unless (eq '<> a)
                 collect (list v a))
       (lambda ,(loop for a in args
                      for v in vars
                      if (eq '<> a)
                      collect v)
(,fn ,@vars)))))

(Edited to fix an embarrassing bug. Funny how often those wait to come up till you publish them.)

Dan Shappir - Re: Currying of Complex Interfaces  blueArrow
2/8/2004; 1:02:57 PM (reads: 158, responses: 1)
BeyondJS can curry most any way you like, see here. And using Rhino you can interface with all the JVM services and compile to a class. BeyondJS even provides a BeyondRhino package that makes this a lot easier.

A nice feature in the context you are describing is the ability to use a "map" object to specify the values of various arguments, e.g.

var args = {
  first : "hello",
  second : 3,
  third : f // a function
var g = h.curry(args);

andrew cooke - Re: Currying of Complex Interfaces  blueArrow
2/8/2004; 3:22:07 PM (reads: 159, responses: 0)
that's (the map object) exactly the kind of thing i was looking for. thanks for the pointer.

Stefan Ljungstrand - Re: Currying of Complex Interfaces  blueArrow
2/9/2004; 3:36:47 PM (reads: 103, responses: 1)
Hmm, I thought one might perhaps be able to do this in Hugs + Trex :

-- Signature of function we want to "curry" foo :: Rec (a :: Int,b :: Bool,c :: Char) -> String

Then we could "curry" this like :

foo . (c = 'c',a = 42 |)

(I would call that a record "section".)

Unfortunately it seems like they haven't thought of this "section" (at least not implemented it). So this is what one can do ATM :

Foo> :t foo . (r -> (c = 'c',a = 42 | r)) foo . (r -> (a=42, c='c' | r)) :: Rec (b :: Bool) -> [Char]

Which doesn't look quite as pretty :(

andrew cooke :

(Just a wild idea : )

Hmm, what if we had a "syntactic application" operator

(:@) :: (a -> b) -> a -> b

which we could *pattern-match* on ? (Probably this "application" would be performed as an ordinary one, the moment in which we force it in any other way than pattern-matching on a :@ pattern. Hmm, that feels strange.)

Well, hm, the "a" type would probably then be treated the same as a existentially quantified variable, I think, So that probably would mean that we couldn't do something interesting with this, like checking that "a" is e.g. equal to "String" ..

(A little related perhaps to Dale Miller's "An Extension to ML to Handle Bound Variables in Data Structures",

Well, nevermind.

andrew cooke - Re: Currying of Complex Interfaces  blueArrow
2/9/2004; 6:10:51 PM (reads: 108, responses: 0)
thanks. in case anyone else is as uninformed as i was, here's some background.

trex is a hugs extension - - and is described here -

ghc was going to have something similar - - but that turned out to be expensive, so a simpler solution was proposed - - but doesn't seem to have been implemented.

now i know what people are talking about when they complain about support for records in haskell...