Calculating type Haskell - haskell

How to calculate type of (.)(.) in Haskell?
I know that it should be
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
But how to calculate it without computer?

(.) :: (b -> c ) -> ((a -> b) -> (a -> c))
(.) :: ((e -> f) -> ((d -> e) -> (d -> f)))
(.)(.) :: ((a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f))))
(.)(.) :: (a -> (e -> f)) -> (a -> ((d -> e) -> (d -> f)))
(.)(.) :: (a -> e -> f) -> a -> ((d -> e) -> (d -> f))
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> (d -> f)
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> d -> f

by (manual) pattern-matching and rewriting types-variables
(.) has type (b -> c) -> ((a -> b) -> a -> c) so the first argument should have type b -> c.
Now if we use it again we have to substitute b with b' -> c' and c with (a' -> b') -> a' -> c') (the second (.) should have type (b' -> c') -> ((a' -> b') -> a' -> c')) and we get
(a -> b' -> c') -> a -> (a' -> b') -> a' -> c'
which is (after renaming) the same as above.
Note that I used a -> b -> c = a -> (b -> c) here
using GHCi
yeah I know - you want it by hand - but GHCi is such a valuable tool that you really should use it to confirm your manual labor.
Here from a terminal:
$ ghci
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Prelude> :t (.)(.)
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
Prelude>
as you can see the type is (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
btw: :t is short for :type and you can see all commands with :help from inside a GHCi session.

Since I wasn't particularly satisfied with the missing explanations in the accepted answer, I give my POV as well:
-- this is the original type signature
(.) :: (b -> c) -> (a -> b) -> a -> c
-- now because of haskell polymorphism,
-- even 'b' and 'c' and so on could be functions
--
-- (.)(.) means we shove the second function composition
-- into the first as an argument.
-- Let's give the second function a distinct type signature, so we
-- don't mix up the types:
(.) :: (e -> f) -> (d -> e) -> d -> f
-- Since the first argument of the initial (.) is of type (b -> c)
-- we could say the following if we apply the second (.) to it:
(b -> c) == (e -> f) -> (d -> e) -> d -> f
-- further, because of how currying works, as in
(e -> f) -> (d -> e) -> d -> f == (e -> f) -> ((d -> e) -> d -> f)
-- we can conclude
b == (e -> f)
c == (d -> e) -> d -> f
-- since we passed one argument in, the function arity changes,
-- so we'd actually only have (a -> b) -> a -> c left, but that
-- doesn't represent the types we have now, so we have to substitute
-- for b and c, so
(a -> b) -> a -> c
-- becomes
(.)(.) :: (a -> (e -> f)) -> a -> (d -> e) -> d -> f
-- and again because of currying we can also write
(.)(.) :: (a -> e -> f) -> a -> (d -> e) -> d -> f

Related

Finding the type of a composition function in Haskell

Let's say I have the following function in Haskell:
compose2 = (.) . (.)
How would I go about finding the type of this function? Because of the multiple compositions I get stuck trying to determine what the type of this function would be.
I know I can use :t compose2 to get the type. However, I want to know how to do it without the aid of a computer. What steps should I take to find the type?
It might help if we fist give the composition functions a more unique identifier, for example:
compose2 = (.)₂ .₁ (.)₃
that way it is easier to refer to some function. We can also convert this to a more canonical form, like:
compose2 = ((.)₁ (.)₂) (.)₃
so now we can start deriving the function type. We know that (.) has type (.) :: (b -> c) -> (a -> b) -> a -> c, or more canonical (.) :: (b -> c) -> ((a -> b) -> (a -> c)). Since the type variables are not "global", we thus can give the tree functions different names for the type variables:
(.)₁ :: (b -> c) -> ((a -> b) -> (a -> c))
(.)₂ :: (e -> f) -> ((d -> e) -> (d -> f))
(.)₃ :: (h -> i) -> ((g -> h) -> (g -> i))
so now that we have given the different composition functions a signature, we can start deriving the types.
We know that (.)₂ is the parameter of a function application with (.)₁, so that means that the type of the parameter (b -> c) is the same as the type (e -> f) -> ((d -> e) -> (d -> f)), and therefore that b ~ (e -> f), and c ~ ((d -> e) -> (d -> f)).
We furthermore know that the type of the "second" parameter of (.)₁ is the same as the type of (.)₃, so (a -> b) ~ ((h -> i) -> ((g -> h) -> (g -> i))), and therefore a ~ (h -> i), and b ~ ((g -> h) -> (g -> i)), therefore the "return type" of (.)₁, which is (a -> c) can thus be specialized to:
((.)₁ (.)₂) (.)₃ :: a -> c
and since a ~ (h -> i), and c ~ (d -> e) -> (d -> f):
((.)₁ (.)₂) (.)₃ :: (h -> i) -> ((d -> e) -> (d -> f))
we know that b is equivalent to both b ~ (e -> f) and b ~ ((g -> h) -> (g -> i)), so that means that e ~ (g -> h), and f ~ (g -> i), we thus can specialize the signature further to:
((.)₁ (.)₂) (.)₃ :: (h -> i) -> ((d -> (g -> h)) -> (d -> (g -> i)))
which is a more verbose form of:
(.)₂ .₁ (.)₃ :: (h -> i) -> (d -> g -> h) -> d -> g -> i
If we automatically derive the type, we obtain:
Prelude> :t (.) . (.)
(.) . (.) :: (b -> c) -> (a1 -> a -> b) -> a1 -> a -> c
If we thus replace b with h, c with i, a1 with d and a with g, we obtain the same type.

Why does (.) map have this type?

I tried to find the type of the function (.) map but somehow find that it is ((a -> d) -> (a -> e)) -> ([d] -> [e]) which according to GHCI is not correct because it should be (.) map :: (a1 -> a2 -> b) -> a1 -> [a2] -> [b].
What am I doing wrong?
Deriving the type...
We have as ingredients:
(.) :: (b -> c) -> (a -> b) -> a -> c
map :: (d -> e) -> [d] -> [e]
(here I used different type identifiers for the two functions to avoid any confusion). A more verbose form (where we make it more explicit that every function takes exactly one parameter) is:
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
map :: (d -> e) -> ([d] -> [e])
Since map is the first parameter of (.) that means that its type (d -> e) -> ([d] -> [e]) should match the input type of the (.) function (so b -> c). This thus means:
b -> c
~ (d -> e) -> ([d] -> [e])
------------------------------
b ~ (d -> e), c ~ ([d] -> [e])
So that means that the result type of (.) map is:
(a -> b) -> (a -> c)
which is equivalent to:
(a -> (d -> e)) -> (a -> ([d] -> [e]))
or less verbose:
(.) map :: (a -> d -> e) -> a -> [d] -> [e]
... and its implementation
The (.) function can be seen as (.) f g == \x -> f (g x). So that means that our function
h = (.) map
is equivalent to:
h f x = map (f x)
It thus takes as input a function f and an object x, and than performs a map with f x as function.
Semancially you could say that we make a "map where one has to inject a 'contect'-objecct" of type a. This context is then taken into account by the processor. This could be useful if we want to apply multiple maps, each with a small change, and thus first pass a "context-object". This is of course an interpretation of humans. For a compiler, the x can have any use, interpretation, etc.
You have probably tried to match the functions by looking at the definition
Types of the two functions
(.) :: ((b -> c) -> (a -> b) -> a -> c)
map :: (d -> e) -> [d] -> [e]
and then trying to match d to b and e to c. Which gives you ((a -> d) -> (a -> e)) -> ([d] -> [e]), now you could match [d] to a and [e] to d. This is however not correct because according to the type definition of map, e and d could be of different type, i.e. d could be of type [e] but it doesn't have to.
The correct way to find the type of this function is to look at the definition of the types
Types of the two functions
(.) :: ((b -> c) -> (a -> b) -> a -> c)
map :: (d -> e) -> [d] -> [e]
and then to match (d -> e) to b and [d] -> [e] to c which gives you (a -> (d -> e)) -> a -> ([d] -> [e]), by removing the superfluous brackets and renaming the type variables you get (a -> b -> c) -> a -> [b] -> [c]. This is the same result GHCI gives you.
When I don't understand the type of a function, I write types using different letters:
(.) :: (b -> c) -> (a -> b) -> a -> c
map :: (x -> y) -> [x] -> [y]
now we are providing map as the first argument of (.) so we can deduce:
b -> c == (x -> y) -> [x] -> [y] -- by matching first arguments we get...
b == x -> y
c == [x] -> [y]
since we have already provided the first argument of (.), the whole b -> c part disappears.
(.) map :: (a -> b) -> a -> c -- Using the above equations for b and c
(.) map :: (a -> x -> y) -> a -> [x] -> [y] -- changing variables names
(.) map :: (a1 -> a2 -> b) -> a1 -> [a2] -> [b]
as GHCi plots

Bird name for the (=<<) combinator?

The Haskell aviary combinators lists (=<<) as:
(a -> r -> b) -> (r -> a) -> r -> b
Is there an official bird-name for this? Or can it be derived via the pre-existing ones?
Is there an official bird-name for this?
I can't find it in Data.Aviary.Birds, so I suppose there's not. If there was, it probably would've been referenced in the list you linked.
Or can it be derived via the pre-existing ones?
Surely. The easiest might be to start with the starling whose signature is similar, and just compose it with flip, i.e.
(=<<) = bluebird starling cardinal
maybe will be correctly like: blackbird warbler bluebird
this is like
(...) = (.) . (.) -- blackbird
(.) -- bluebird
join -- warbler
-- and your function will be
f = join ... (.)
Quoting a comment:
Btw do you have any advice on how to combine combinators to get a specific signature? I feel like I'm missing some trick (my current technique of staring at a list and doing mental gymnastics doesn't scale too well!)
Let the types guide you. You are looking for:
-- This name is totally made-up.
mino :: (b -> a -> c) -> (a -> b) -> a -> c
While you won't find it in the list, there is something quite similar:
starling :: (a -> b -> c) -> (a -> b) -> a -> c
If only we had a way to somehow twist starling into what we want...
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = f starling
-- f :: ((a -> b -> c) -> (a -> b) -> a -> c) -> (b -> a -> c) -> (a -> b) -> a -> c
This mysterious f has a rather unwieldy type, so let's abbreviate it for a moment: with x ~ b -> a -> c, y ~ a -> b -> c and z -> (a -> b) -> a -> c, we have
f :: (y -> z) -> x -> z
Another look at the list shows this fits the result type of queer:
queer :: (a -> b) -> (b -> c) -> a -> c
Progress!
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = queer g starling
-- g :: x -> y
-- g :: (b -> a -> c) -> a -> b -> c
As for g, there is a great candidate near the top of the list:
cardinal :: (a -> b -> c) -> b -> a -> c
And there it is:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = queer cardinal starling
queer, of course, is cardinal bluebird (i.e. reverse function composition), which leads us back to Bergi's bluebird starling cardinal.
GHC can actually assist you with this kind of derivation:
import Data.Aviary.Birds
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = _f starling
GHCi> :l Mino.hs
[1 of 1] Compiling Main ( Mino.hs, interpreted )
Mino.hs:4:8: error:
* Found hole:
_f
:: ((a0 -> b0 -> c0) -> (a0 -> b0) -> a0 -> c0)
-> (b -> a -> c) -> (a -> b) -> a -> c
Where: `b0' is an ambiguous type variable
`a0' is an ambiguous type variable
`c0' is an ambiguous type variable
`b' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:3:1-43
`a' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:3:1-43
`c' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:3:1-43
Or perhaps `_f' is mis-spelled, or not in scope
* In the expression: _f
In the expression: _f starling
In an equation for `mino': mino = _f starling
* Relevant bindings include
mino :: (b -> a -> c) -> (a -> b) -> a -> c (bound at Mino.hs:4:1)
|
4 | mino = _f starling
| ^^
Failed, no modules loaded.
If you want a clean output, though, you have to ask gently:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PartialTypeSignatures #-}
import Data.Aviary.Birds
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
mino =
let s :: (a -> b -> c) -> _
s = starling
in _f s
(A type annotation to starling would make defining s unnecessary; that style, however, would get ugly very quickly with more complicated expressions.)
GHCi> :l Mino.hs
[1 of 1] Compiling Main ( Mino.hs, interpreted )
Mino.hs:10:8: error:
* Found hole:
_f
:: ((a -> b -> c) -> (a -> b) -> a -> c)
-> (b -> a -> c) -> (a -> b) -> a -> c
Where: `b' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:6:1-57
`a' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:6:1-57
`c' is a rigid type variable bound by
the type signature for:
mino :: forall b a c. (b -> a -> c) -> (a -> b) -> a -> c
at Mino.hs:6:1-57
Or perhaps `_f' is mis-spelled, or not in scope
* In the expression: _f
In the expression: _f s
In the expression:
let
s :: (a -> b -> c) -> _
s = starling
in _f s
* Relevant bindings include
s :: (a -> b -> c) -> (a -> b) -> a -> c (bound at Mino.hs:9:9)
mino :: (b -> a -> c) -> (a -> b) -> a -> c (bound at Mino.hs:7:1)
|
10 | in _f s
| ^^
Failed, no modules loaded.
The process described above still involves quite a bit of staring at the list, as we are working it out using nothing but the birds in their pointfree majesty. Without such constraints, though, we would likely proceed in a different manner:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = _
The hole has type a -> c, so we know it is a function that takes an a:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> _
-- x :: a
The only other thing that takes an a here is g:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> g _ x
The type of the hole is now b, and the only thing that gives out a b is f:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> g (f x) x
This, of course, is the usual definition of the reader (=<<). If we flip g, though...
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> flip g x (f x)
... the reader (<*>) (i.e. the S combinator) becomes recogniseable:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino g f = \x -> (<*>) (flip g) f x
We can then write it pointfree...
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = (<*>) . flip
... and translate to birdspeak:
mino :: (b -> a -> c) -> (a -> b) -> a -> c
mino = bluebird starling cardinal

Is the a way to write a function with this signature?

I've got a function that's doing something currently working with particular datatypes. I was wondering if I could make it a general. Here's a generalised version of it's signature:
f :: Monad m => ((a -> b) -> c -> d) -> (a -> m b) -> m c -> m d
If the above can't be written, perhaps the more restricted version can?
f2 :: Monad m => ((a -> a) -> b -> b) -> (a -> m a) -> m b -> m b
No, it is impossible, at least without non-termination or unsafe operations.
The argument is essentially similar to this one: we exploit f to inhabit a type which we know can't be inhabited.
Assume there exists
f :: Monad m => ((a -> b) -> c -> d) -> (a -> m b) -> m c -> m d
Specialize c ~ ()
f :: Monad m => ((a -> b) -> () -> d) -> (a -> m b) -> m () -> m d
Hence
(\g h -> f (\x _ -> g x) h (return ()))
:: Monad m => ((a -> b) -> d) -> (a -> m b) -> m d
Speciazlize d ~ a.
(\g h -> f (\x _ -> g x) h (return ()))
:: Monad m => ((a -> b) -> a) -> (a -> m b) -> m a
Speclialize m ~ Cont t
(\g h -> runCont $ f (\x _ -> g x) (cont . h) (return ()))
:: ((a1 -> b) -> a) -> (a1 -> (b -> r) -> r) -> (a -> r) -> r
Take h = const
(\g -> runCont $ f (\x _ -> g x) (cont . const) (return ()))
:: ((r -> b) -> a) -> (a -> r) -> r
Hence
(\g -> runCont (f (\x _ -> g x) (cont . const) (return ())) id)
:: ((r -> b) -> r) -> r
So, the type ((r -> b) -> r) -> r is inhabited, hence by the Curry-Howard isomoprhism it corresponds to a theorem of propositional intuitionistic logic. However, the formula ((A -> B) -> A) -> A is Peirce's law which is known to be non provable in such logic.
We obtain a contradiction, hence there is no such f.
By contrast, the type
f2 :: Monad m => ((a -> a) -> b -> b) -> (a -> m a) -> m b -> m b
is inhabited by the term
f2 = \ g h x -> x
but I suspect this is not what you really want.
There's a problem. Knowing c doesn't give you any information about which as will be passed to (a -> b). You either need to be able to enumerate the universe of as or be able to inspect the provided a arguments with something like
(forall f. Functor f => ((a -> f b) -> c -> f d)
In which case it becomes almost trivial to implement f.
Instead of trying to implement f in general, you should try to generalize your functions like ((a -> b) -> c -> d) to see if you can replace them with lenses, traversals, or something similar.

function composition type inference in haskell

In haskell, the type of (.) function is:
(.) :: (b -> c) -> (a -> b) -> a -> c
And the type of (.) (.) is:
(.) (.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
I am not able to deduce the result, how is this done?
(.) :: (b -> c) -> (a -> b) -> a -> c
Let's go through it. First thing this function takes is (b -> c) (so a function from b to c), cool. By adding a pair of (redundant) parentheses:
(.) :: (b -> c) -> ((a -> b) -> a -> c)
^-- I am b' ^-- I am c' -- (b' and c' not to have name clash)
That first part, we gave to the function (i.e. has been taken care of):
(.) (.) :: (a -> b') -> a -> c'
-- after substituting stuff (b' and c')
(.) (.) :: (a -> (b -> c)) -> a -> ((a1 -> b) -> a1 -> c)
^-- of course a1 /= a
-- you could eliminate redundant parentheses
(.) (.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
-- wee
I hope this settles it. Main point is: type inference is easy to 'get' and once you get it is only a matter of substitution to reach what ghci automagically infers.
ot: we could call this quizzical operator boobs.

Resources