Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement flip in Scala like it is implemented in Haskell?

Tags:

haskell

scala

Is it possible to implement flip in Scala like it is implemented in Haskell?

http://hackage.haskell.org/package/base-4.7.0.1/docs/src/GHC-Base.html#flip

flip                    :: (a -> b -> c) -> b -> a -> c
flip f x y              =  f y x
like image 733
jhegedus Avatar asked Aug 17 '14 13:08

jhegedus


2 Answers

Well, this is a fairly literal translation:

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

Now you can write the following:

scala> def append: String => String => String = a => a + _
append: String => (String => String)

scala> append("foo")("bar")
res0: String = foobar

scala> val flipped = flip(append) _
flipped: String => (String => String) = <function1>

scala> flipped("foo")("bar")
res1: String = barfoo

You could argue that the following is a little closer to the spirit of the Haskell version:

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

Now you don't have to eta-expand the partially-applied method:

scala> val flipped = flip(append)
flipped: String => (String => String) = <function1>

scala> flipped("foo")("bar")
res2: String = barfoo

So you've got a couple of choices. It's not really clear that one is more like the Haskell implementation, but given the distinction that Scala makes between methods and functions they're both pretty close.

like image 76
Travis Brown Avatar answered Oct 20 '22 05:10

Travis Brown


Another way, more closer to Haskell version:

scala> def flip[a, b, c]: (a => b => c) => b => a => c = f => x => y => f(y)(x)
flip: [a, b, c]=> (a => (b => c)) => (b => (a => c))

scala> val f: Int => Char => String = i => c => f"Int($i) and Char($c)"
f: Int => (Char => String) = <function1>

scala> val g = flip(f)
g: Char => (Int => String) = <function1>

Or this:

scala> def flip[a, b, c]: (a => b => c) => b => a => c = {
     |   case f => x => y => f(y)(x)
     | }
flip: [a, b, c]=> (a => (b => c)) => (b => (a => c))


scala> g('a')(100)
res0: String = Int(100) and Char(a)

scala> f(100)('a')
res1: String = Int(100) and Char(a)
like image 22
Eastsun Avatar answered Oct 20 '22 04:10

Eastsun