0

I'm trying to understand Haskell function types right now. Let's say I want to compose two functions f1 and f2 (suppose I don't know their definition). The function signature of f2 . f1 is:

f1 . f2 :: (Fractional (a -> a), Num a) => a -> (a -> a) -> a -> a 

How do I read this signature and more specifically, how do I know how to apply arguments to this composition?

e.g. how can I read the type information of f1 . f2 to be able to write valid expressions like

(f1 . f2 2) 3 4 (f1 2. f2 2) 4 

1 Answer 1

2

That signature means you haven't composed them correctly. You don't get a type error, because in theory some madman might give functions a Fractional instance, but in real life that never happens. So there is no set of arguments you can apply to (f1 . f2) that will typecheck.

Instead, back up and look at the types of f1 and f2. What are they? I predict that they are both two-argument functions, because your type is the one I get when I write

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

You can't really compose a two-argument function, because composition is for one-argument functions. But you can partially apply the functions before composing, if you like, to make them into one-argument functions. And that's exactly what you've done in your last example, which works fine:

Prelude> f1 = (/) Prelude> f2 = (+) Prelude> (f1 2 . f2 2) 4 0.3333333333333333 
Sign up to request clarification or add additional context in comments.

7 Comments

But both deriving via (Ap ((->) b) a) instance Num a => Num (b -> a) and an instance for Church numerals are just sitting right there begging me to write them! :)
technically, (/) . uncurry (+) is also a possibility.
@JosephSible-ReinstateMonica it's worse than that. it's actually Fractional. writing a recip method for functions should be extra fun!
@WillNess Isn't that just recip = (recip .)?
Thanks to all, may be, I should have asked for f1 . f2 :: (Num a, Num (a -> a)) => a -> (a -> a) -> a -> a instead. @amalloy I understand from your answer that composing f1 . f2 is not allowed since they are intended to have two arguments. But: GHCI doesn't complain composing them and I thought they are "transformed" into one-argument function either way. I am still in the dark about the reading of the signature: So, what is the (human) reading of a -> (a -> a) -> a -> a and, can I infer the application of the arguments from this reading?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.