3

Let's look at these functions' types for example:

:t traverse
traverse
  :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

:t id
id :: a -> a

They have no concrete types, but have generic type parameters: a, f, b, t (correct me if they called not generic type parameters please)

If I combine id and traverse together in this way,

:t traverse id [Just 1, Just 2, Nothing] 
traverse id [Just 1, Just 2, Nothing] :: Num b => Maybe [b]

Haskell can now bind some concrete types for the type variables a, f, b, t.

t = []
a = Maybe bb
f = Maybe
b = Num bb => bb

Below I infer the types and mappings to parameters by hand, is there any way or tool in Haskell to do this automatically, so that it takes some composed parts (id and traverse) in an example, extracts their type signatures in general, and on output produces a mapping from generic type parameters names to concrete inferred types?

See also the first example here: https://wiki.haskell.org/Type_inference for expression "map ord" on how Haskell finds bindings of actual types to names.

So when we look at functions separately we only have names a, f, b, t. But then we combine the functions and provide some extra information like [Just 1, Just 2, Nothing], and the names a, f, b, t are mapped to concrete types.

I want to catch and show this mapping automatically.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Evg
  • 2,978
  • 5
  • 43
  • 58
  • 1
    I’ve voted to reopen this question. I don’t know if you’ll get a satisfying *answer*, but it’s clear to me what you’re asking: to automatically print out the *substitution* of type variables that the compiler deduces during typechecking when instantiating the type of a polymorphic definition. I.e., given `f :: forall x1…xn. t` with type variables `x1`…`xn` and type `t`, and an expression containing `f`, this would print all the values (of kind `Type`) chosen for `x1`…`xn`. You may find the information you want in the output of the GHC flags `-ddump-tc`, `-ddump-tc-ast`, or `-ddump-tc-trace`. – Jon Purdy Dec 12 '20 at 01:37
  • If I was in error closing it, please correct me. – Will Ness Dec 12 '20 at 15:17
  • @JonPurdy, I've mistakely voted for reopening this question withouth seeing that your comment is from 13 hours ago while Will Ness closed this question only a few minutes ago, so probably you agree (as I agree) with the dupe that Will marked. – Enlico Dec 12 '20 at 15:17
  • @WillNess, I think you're not wrong, even if I'm biased as I asked _that_ question exactly to dupe this (what a pity there's no golden badge for creating a newer question which an older question gets marked as a duplicate of :P). But Jon probably sees in this question another meaning that I don't see. – Enlico Dec 12 '20 at 15:19
  • @Enlico: Your question shows how to get the type of a subexpression; in order to answer this question, you take that result and manually unify it with the original polymorphic type to obtain the desired result, a substitution like { `f` ↦ `Maybe`, `t` ↦ `[]`, `a` ↦ `Maybe b0`, `b` ↦ `b0` }. That works fine for functions, although not so much for more complex subterms. It is certainly a way to get there, just not exactly what I think was asked for—namely, the substitution. – Jon Purdy Dec 14 '20 at 19:40
  • @JonPurdy ok then. I've already voted for reopening. – Enlico Dec 14 '20 at 19:43

1 Answers1

-1

I think f and t are more generic type constructor parameters, as they act on a type to give you a type (they kind is * -> *, where * means "a concrete type").

traverse id is not composition, it is function application, as you are passing id as an argument to traverse. this . that is function composition between this and that, in the mathematical sense, where you create a function that gives its (first) argument as an input to that and feeds the result of this application to this.

You refer to the example in this page, where given this

map :: (a -> b) -> [a] -> [b]
Char.ord :: (Char -> Int)

the compiler is able to deduce that the type of map ord is [Char] -> [Int], as you can check yourself by writing :t map ord at the command line.

If you expect a similar output with concerete types when you type :t traverse id, you won't get it, for the simple reason that traverse id is still a polymorphic function, both in its concrete type arguments and type constructor arguments.

Just to give a slightly different example, if you type :t traverse (:[]), where (:[]) has type a -> [a], which is a particular case of the (Applicative f) => a -> f b that traverse expects, you get this output,

traverse (:[]) :: Traversable t => t b -> [t b]

which, compared with :t traverse,

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

tells you that traverse, in traverse (:[]), has been "instantiated" with f === [] and a === b.

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • I mean not function composition, I mean that I combine two things (functions) together and this combining determines how to correspond names to actual types. – Evg Dec 11 '20 at 18:12
  • @Evg, that "combine two things" is _function application_. However, as regards what you want, I still don't get it, sorry (and since the question is closed, at least other two persons agree with me). Maybe you can write in the question an example output that you expect from some wannabe-command or somthing. – Enlico Dec 11 '20 at 18:14
  • Please look at first example here: https://wiki.haskell.org/Type_inference for expression "map ord" how Haskell find bindings of actual types to names. I also update the question. – Evg Dec 11 '20 at 18:34
  • @Evg, please give a look at my updated answer. I strongly advice you to edit your question to clarify _**with code**_ what you mean. The question is still closed, that means whoever is passing by is not willing to reopen it because they don't find it clear, just like me. – Enlico Dec 11 '20 at 18:52
  • 1
    @Evg, please also give a look at [this question](https://stackoverflow.com/questions/65258061/can-i-print-in-haskell-the-type-of-a-polymorphic-function-as-it-would-become-if) I've just asked. Is that, by any chance, what you were really trying to ask here? – Enlico Dec 11 '20 at 20:24