functors in scala and haskell part 3

2010-07-13 comments | scala, haskell, functors, programming
history

functors don't only work on data structures, but also on functions. so fmap'ing the function (*3) :: (Num a) => a -> a over another function like (+100) :: (Num a) => a -> a results in a new function which apply (*3) to the result of (+100).

this sounds like something we already know. yeah, function composition with the dot (.) function. therefore the functor instance for functions must be written like this:

instance Functor ((->) r) where  
    fmap = (.)

this instance is defined in the Control.Monad.Instances module. here some examples

import Control.Monad.Instances

f1 = (100 +)
f2 = (3*)
f3 = fmap (++ "_FOO") show

main::IO()
main = do
   putStrLn $ show $ fmap f2 f1 1
   putStrLn $ show $ fmap (*3) (+100) 1
   putStrLn $ show $ fmap f3 [10,20,30]

resulting in the following output

> runhaskell fmaps2.hs
303                              
303
["10_FOO","20_FOO","30_FOO"]

pretty cool imho. now the same in scalaz:

import Scalaz._

val f1 = (x: Int) => 100 + x
val f2 = (x: Int) => 3 * x

assert((f1 map f2)(Functor.Function1Functor)(1) === 303)
assert((f1 map f2).apply(1) === 303)
assert(((1).pure[Identity] map f1 map f2) === 303)
assert(((1).pure[Identity] map (100+) map (3*)) === 303)

assert((List(10,20,30) map (_.toString) map (_ ++ "_FOO")) ===
        List("10_FOO", "20_FOO", "30_FOO"))

I think this is relative straight forward. one problem are the implicit parameters when we try to call the new mapped function. so best call the apply(...) function directly.

another little problem is the need of the pure function on our sample value 1. scala need this type lifting to Identity to get the map function ready for our value. maybe I'm wrong here and there is a better and simpler solution. any hint is welcome.

so much for functors on functions.

hth

blog comments powered by Disqus