I think you mean

1
2
let func1 x y = x * y;;

and:

1
2
let func2 (x,y) = x * y;;

These are different: the latter is a function taking a tuple as a single argument. The former is a function taking arguments in "iterated" or "curried" form. When you apply it to its first argument you get a residual function - you can choose when you want to apply the second argument. This is explained (fairly briefly) in Chapter 2 of the Expert F# book whose draft is available here.

This is useful when doing things like:

1
2
3
4
 

map (func1 3) [4;5;6]
By on 9/18/2006 3:47 PM ()

Hmm. Because F# is a functional-programming language, I expected that

func1 x y

would have applicative structure (func1 x) y, but then examples using

printf "format-string" arg1 arg2 ... argn

really threw me and I had to conclude that I really don't know the rules for ML and F#. I guess I had better read that chapter.

By on 9/23/2006 3:29 PM ()

You are correct that F# has the applicative structure ((func1 x) y). printf matches this, but format strings are treated as special by the language and by the compiler in the same way as OCaml. There is an all-to-brief mention of this in the informal language specification at [link:research.microsoft.com]. Here are some more details.

For example, printf "%d" has type int -> unit, and printf "%d%d" has type int -> int -> unit. That is, the return type of printf depends on the structure of the format string passed to as the first argument. You can see this by looking at the signature of printf itself, which is:

val printf: 'a channel_format -> 'a

How does this work? When strings are used as format string types such as channel_format the type checker parses the format string statically and works out what 'a is. (note channel_format is ultimately an abbreviation for the overrarching format string type Format4 mentioned in the informal language spec)

At runtime the format string is still essentialy a string, which gets interpreted and various techniques are used to generate a function value of the right type at runtime, which is then applied to subsequent arguments. You can see the somewhat wild implementation of the runtime interpretation of the format string in prim-printf.fs in the distribution. It's likely we could use other techniques, and I've been meaning to write a technical note on this whole approach to typesafe variadic functions.

One of the nice things about this technique is that it lets you include extensible format specifiers such as %a and %t (see the Printf documentation for these).

Not surprisingly the strong typing doesn't work for dynamically created format strings. Being in the era of dynamic languages someone pointed out to me that it would be nice to have a way to interpret a format string against an obj[] array of arguments. We could and should adjust the current implementation of printf formatting to include this.

Don

By on 9/23/2006 3:56 PM ()

When strings are used as format string types such as channel_format the type checker parses the format string statically and works out what 'a [the signature of (printf "format"), essentially] is. At runtime the format string is still essentialy a string, which gets interpreted and various techniques are used to generate a function value of the right type at runtime, which is then applied to subsequent arguments.

Ah!! I was leafing through your draft Chapter 2 just now and noticed that type inference/checking occurs on the printf arguments against the format string, but the coin still hadn't dropped. Cute.

By on 9/23/2006 5:53 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper