Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is ((+) . (+)) in Haskell?

In ghci,

:t ((+).(+))
> ((+).(+)) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a

but what is this thing? Can any one give me an example of the use of this please?

How can one composite 2 functions that take 2 parameters each? for example, how does (map.map) :: (a -> b) -> [[a]] -> [[b]] work?

(^.^) (-.-) (+.+) (can't help making funny faces out of it. PS: I thought it means to tell the compiler how you feel today)

like image 625
Larry Avatar asked May 23 '14 09:05

Larry


People also ask

What is -> in Haskell?

(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.

What are function types in Haskell?

Functions can also be passed as arguments or returned (as we have seen). Their types are given in the type signature. *Main> :t map map :: (a -> b) -> [a] -> [b] *Main> :t filter filter :: (a -> Bool) -> [a] -> [a] flip_args :: (a -> b -> c) -> b -> a -> c flip_args f x y = f y x.

What does in do in Haskell?

in goes along with let to name one or more local expressions in a pure function.

What does the operator do in Haskell?

Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).


1 Answers

Num (a -> a) (or e.g. Eq (a -> a)) is basically an indicator for code that doesn't make any sense1, but the compiler nevertheless deduces a (nonsensical) type signature. Usually it turns up when you've forgotten to apply a function to some argument. In this case, obviously (+) needs a "plain number" argument to become a "simple function" to which you can post-compose another such function.

However, (a -> a) is sure enough a valid type of functions that you can also pass on, just not as numbers. For instance, map . (+) is a perfectly good combination:

Prelude> :t map . (+)
map . (+) :: Num b => b -> [b] -> [b]
Prelude> zipWith (map . (+)) [10,20,30] [[1,2],[3,4]]
[[11,12],[23,24]]

because map actually expects a function as its first argument. Similarly,

Prelude> zipWith (map . map) [(+10),(+20),(+30)] [[[1,2],[3,4]],[[5,6]]]
[[[11,12],[13,14]],[[25,26]]]

Here, the right map takes a simple function (like numerical increment) and returns the corresponding list-map function. That function is then fed to the left map resulting in a function that maps nested lists.


1Actually, you can force it to make sense by defining

instance (Num a) => Num (b -> a) where
  fromInteger x = const $ fromInteger x
  f + g = \x -> f x + g x

Personally, I'm not a fan of this. It confusing, for instance let a = 3 in 4 a produces 4 when most people would expect multiplication to 12.

like image 143
leftaroundabout Avatar answered Oct 28 '22 04:10

leftaroundabout