2/8/09

Flavors of Curry: Scala vs Haskell


Scala is a nice language to explore functional programming, and for me it was easy to use it as a “stepping stone” and jump to Haskell with all the purity and laziness (I think is because I'm the kind of guy that enter slowly in the cold water...). I'm using Haskell to learn the theory and tools of functional programming (in a language that forces you to), so I can use them in Scala.

To that end, I'm going through “Learn You a Haskell for Great Good!” (I seem to have a fondness for technical books with silly images). Usually I'll try to do the same exercises in Scala to compare.

I was going through the chapter about higher order functions and currying. What are curried functions? You can find a very good explanation in wikipedia (of course!). Basically is the transformation of a function with multiple parameters into another function with only one parameter that returns a function of the remaining parameters. With that, your language can care only about functions with only one parameter and still be equally powerful. The advantage is if you call a function with less parameters, you get a partially applied function.

One of the examples on the “Learn you...” is a “flip” function: a function that exchanges the first and second parameter of a given function. In Haskell is as easy as:

flip1 f x y = f y x

That's all! Hindley-Milner type inference ensures the type safety:

flip1 :: (t1 -> t -> t2) -> t -> t1 -> t2

As an example:


f x y =x/y
f 1 2
0.5

g= flip1 f
g 1 2
2.0


BTW, there's something odd:


Prelude> let flip1 f x y = f y x
Prelude> :t flip1
flip1 :: (t1 -> t -> t2) -> t -> t1 -> t2
Prelude> let f x y =x/y
Prelude> :t f
f :: (Fractional a) => a -> a -> a
Prelude> let g=flip f
Prelude> :t g
g :: Double -> Double -> Double
Prelude> :t flip1 f
flip1 f :: (Fractional t1) => t1 -> t1 -> t1



The type of flip1 f is (Fractional t1) => t1 -> t1 -> t1, meaning that t1 is restricted to be of Fractional typeclass, but if I bind g to flip f, now the type is Double... that's not what one would expect! (Any Haskell expert can tell me what's happening?)


As usual, I'll tried to do the same in Scala to see how far it can goes.
The main difference is of course, type inference: in Scala you need to declare the function types. The other major difference is Haskell every function is curried by default, in Scala you need to explicitly curry the function by separating each parameter between parentheses.

In Scala, our (curried) f function will be:


def f(x:Int)(y:Int)=x/y
f: (Int)(Int)Int


The flip function in Scala would be:


def flip1[A,B,C]( f:A=>B=>C)(x:B)(y:A) =f(y)(x)
flip1: [A,B,C]((A) => (B) => C)(B)(A)C


Is clearly more verbose than the Haskell version, but equally powerful:


def g = flip1 (f) _
g: (Int) => (Int) => Int



The underscore is needed to get the partially applied function and the f must be in parentheses (again, all curried parameters must have their own parentheses).


Conclusion? Nothing. Haskell and Scala are obviously different, but they share some common ground... just wanted to show it :)

8 comments:

Don Stewart said...

I'm a little curious: why not just use Haskell?

mp said...

The Double comes from the Haskell's monomorphism restriction, try
let h x = flip f x
and it will have the expected polymorphic type.

Gabriel C. said...

@mp Thanx! It makes sense

@Don use Haskell... for what?

Don Stewart said...

> I'm using Haskell to learn the theory and tools of functional programming (in a language that forces you to), so I can use them in Scala

Why go back to Scala at all then?

Gabriel C. said...

@Don:
Because I want to embed my apps to in a JVM environment and Jaskell is not mature enough?
Because I still think that OO is powerful tool to map (non-math) problem spaces into the computing solution space?
Because doing the same thing in 2 different languages help me to better understand both languages and the concept?
Because I want ? :)

klausmeier said...

If you like haskell and you want run your programs on the jvm, try CAL / Quark (which has a great Eclipse IDE and something like ghci (= ice) too).
http://labs.businessobjects.com/cal/
"A lazily evaluated, strictly-typed language called CAL, with many similarities to Haskell". Btw. we use it in production systems.
Klaus Meier (iba-cg.de)

Bombjack said...

I don't think much of the black-on-black colour scheme!

Anonymous said...

nice example!
Could you link us some real world cases where currying could be useful?
I'll learnign Scala and I'm fascinated by this feature, but coming from Java I'm still twisting my frozen mind, and trying to build the ground for Functional Programming.