Haskell calculated type

How to calculate type (.) (.) In Haskell? I know what it should be

(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c

But how to calculate it without a computer?

+4
source share
3 answers
(.)    :: (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
+8
source

using (manually) pattern matching and rewriting variable types

(.)has a type (b -> c) -> ((a -> b) -> a -> c), so the first argument must be of type b -> c. Now, if we use it again, we must replace bwith b' -> c'and cby (a' -> b') -> a' -> c')(the second (.)must be of type (b' -> c') -> ((a' -> b') -> a' -> c')), and we will get

(a -> b' -> c') -> a -> (a' -> b') -> a' -> c'

which is (after renaming) the same as above.

Please note that I used a -> b -> c = a -> (b -> c)here

using GHCi

, - , GHCi - , , .

:

$ ghci
GHCi, version 7.10.1: http://www.haskell.org/ghc/  :? for help
Prelude> :t (.)(.)
(.)(.) :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c
Prelude> 

, (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c

btw: :t :type, :help GHCi.

+5

Since I was not particularly pleased with the missing explanations in the accepted answer, I also give my POV:

-- 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 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
0
source

Source: https://habr.com/ru/post/1584714/


All Articles