2

So I have been using F# for a while and studying a bit of Haskell on the side and I have realized I could rewrite the exact same function one of three different ways.

Either with implicit currying, explicit currying, or with lambda expressions.

//lambdas
let add'  =  fun x -> fun y -> x + y

//explicit currying
let add' x  =     
   let subFunction y = 
      x + y                    
   subFunction   

//implicit currying
let add' x y = x + y

All of these have the signature int -> int -> int. All of them do the same thing.

Which one should I use in which case?

1
  • 2
    The one that is most readable and shortest.
    – svick
    Mar 2, 2015 at 13:36

2 Answers 2

5

In the situations similar to the one you've described you should always use the third option, or, better yet, just let add' = (+) (but beware of Monomorhism Restriction). I see no sense in the other two definitions you have provided.

However, it's common to use nested functions in a way similar to your second example if the nested function takes auxiliary arguments, such as an accumulator in tail-recursive functions.

2
  • Yes I was aware of the (+) option, but I did not list it because it was only applicable when converting an infix operator to a function. Mar 2, 2015 at 10:08
  • 4
    I would disagree. Compare this: sum xs = fold (+) xs and this: sum = fold (+). In the second case, you have a (partially applied) function on the right hand side, so it is similar to the let add = (+).
    – M-x
    Mar 2, 2015 at 10:16
2

The answer to your question is the "implicit currying" option. However, there are times where you would use the second option.

In Haskell, for performance, you may want to share some work in the partially applied result. (Note, nothing in the Report guarantees this sharing or precludes the compiler from lifting out the work itself. In practice, GHC doesn't do these sorts of transformations for good reasons.)

addC x = let c = large computation x in \y -> x + y + c

In Haskell this is semantically equivalent to the following though in practice will have different performance characteristics.

addC x y = let c = large computation x in x + y + c

In F# the difference can be semantically meaningful.

let foo x = let rx = ref x in fun y -> rx := !rx + 1; !rx + y;;

is very different from

let foo x y = let rx = ref x in rx := !rx + 1; !rx + y;;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.