Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding type of `5 1`

Tags:

types

haskell

I used this Haskell interpreter right here: https://tryhaskell.org/

When I provided the input 5 1 it tells me - I assume it is the type - that the expression is of type (Num a, Num (a -> t)) => t:

λ 5 1
:: (Num a, Num (a -> t)) => t

Now I have tried to understand how to interpret this and this is what I came up with.

a is any Num type and so is a -> t. The expression results in some type t that is produced by theoretically applying 1 (type a) to 5 (type a -> t).

This really disturbs me because I don't see how the constraint Num (a -> t) makes sense. Theoretically it looks to be the correct interpretation but I can't find prove for that.


The interpretation is correct

It makes sense because Num is a polymorphic type - which can be a function.

like image 275
WorldSEnder Avatar asked Dec 11 '22 00:12

WorldSEnder


2 Answers

Numerals are polymorphic in Haskell. When you write something like

5

The compiler turns this into fromInteger (5 :: Integer) :: Num a => a. The compiler doesn't know beforehand what instance to use, so it'll do it's best to guess from context. If you have 5 1, then the first numeral is a polymorphic Num type, that also must be a function. The second numeral is just seen as a Num, so this is quite normal.

But you may ask "How can a number be a function?" If everything in the world made sense, then numbers wouldn't be functions, but you can actually write an instance for them that behaves, more or less:

{-# LANGUAGE FlexibleInstances #-}

instance Num a => Num (a -> a) where
    fromInteger a = const (fromInteger a)
    a + b = \c -> a c + b c
    a * b = \c -> a c * b c
    abs a = \c -> abs (a c)
    signum a = \c -> signum (a c)
    negate a = \c -> negate (a c)

This satisfies the definition, but it probably wouldn't be very useful. For example:

> let x = 1 :: Int -> Int; y = 2 :: Int -> Int
> x + y $ 0
3
> x + y $ 102089
3
> x + y $ undefined
3

So here, the argument does not matter to the expression, it's not even evaluated. How about a more interesting one:

> let x = (+10); y = (*10)
> x + y $ 0    -- x 0 + y 0 = 0 + 10 + 0 * 10
10
> x + y $ 1    -- x 1 + y 1 = 1 + 10 + 1 * 10
21
> x + y $ 2
32

And so forth. I'm sure someone can find an interesting use case for it, but I wouldn't recommend it, it's quite clearly not very intuitive.

like image 73
bheklilr Avatar answered Dec 30 '22 05:12

bheklilr


In Haskell, numbers are polymorphic:

λ> :t 5
5 :: Num a => a

The important thing to note here is that function application in Haskell is whitespace. So to make something like 5 2 typecheck, all you have to do is create an instance for (a -> a) type.

like image 39
Sibi Avatar answered Dec 30 '22 05:12

Sibi