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?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.