Multiple types for f in this picture? - haskell

https://youtu.be/brE_dyedGm0?t=1362
data T a where
T1 :: Bool -> T Bool
T2 :: T a
f x y = case x of
T1 x -> True
T2 -> y
Simon is saying that f could be typed as T a -> a -> a, but I would think the return value MUST be a Bool since that is an explicit result in a branch of the case expression. This is in regards to Haskell GADTs. Why is this the case?

This is kind of the whole point of GADTs. Matching on a constructor can cause additional type information to come into scope.
Let's look at what happens when GHC checks the following definition:
f :: T a -> a -> a
f x y = case x of
T1 _ -> True
T2 -> y
Let's look at the T2 case first, just to get it out of the way. y and the result have the same type, and T2 is polymorphic, so you can declare its type is also T a. All good.
Then comes the trickier case. Note that I removed the binding of the name x inside the case as the shadowing might be confusing, the inner value isn't used, and it doesn't change anything in the explanation. When you match on a GADT constructor like T1, one that explicitly sets a type variable, it introduces additional constraints inside that branch which add that type information. In this case, matching on T1 introduces a (a ~ Bool) constraint. This type equality says that a and Bool match each other. Therefore the literal True with type Bool matches the a written in the type signature. y isn't used, so the branch is consistent with T a -> a -> a.
So it all matches up. T a -> a -> a is a valid type for that definition. But as Simon is saying, it's ambiguous. T a -> Bool -> Bool is also a valid type for that definition. Neither one is more general than the other, so the definition doesn't have a principle type. So the definition is rejected unless a type is provided, because inference cannot pick a single most-correct type for it.

A value of type T a with a different from Bool can never have the form T1 x (since that has only type T Bool).
Hence, in such case, the T1 x branch in the case becomes inaccessible and can be ignored during type checking/inference.
More concretely: GADTs allow the type checker to assume type-level equations during pattern matching, and exploit such equations later on. When checking
f :: T a -> a -> a
f x y = case x of
T1 x -> True
T2 -> y
the type checker performs the following reasoning:
f :: T a -> a -> a
f x y = case x of
T1 x -> -- assume: a ~ Bool
True -- has type Bool, hence it has also type a
T2 -> -- assume: a~a (pointless)
y -- has type a
Thanks to GADTs, both branches of the case have type a, hence the whole case expression has type a and the function definition type checks.
More generally, when x :: T A and the GADT constructor was defined as K :: ... -> T B then, when type checking we can make the following assumption:
case x of
K ... -> -- assume: A ~ B
Note that A and B can be types involving type variables (as in a~Bool above), so that allows one obtain useful information about them and exploit it later on.

Related

Type inference in where clauses

If I write
foo :: [Int]
foo = iterate (\x -> _) 0
GHC happily tells me that x is an Int and that the hole should be another Int. However, if I rewrite it to
foo' :: [Int]
foo' = iterate next 0
where next x = _
it has no idea what the type of x, nor the hole, is. The same happens if I use let.
Is there any way to recover type inference in where bindings, other than manually adding type signatures?
Not really. This behavior is by design and is inherited from the theoretical Hindley-Milner type system that formed the initial inspiration for Haskell's type system. (The behavior is known as "let-polymoprhism" and is arguably the most critical feature of the H-M system.)
Roughly speaking, lambdas are typed "top-down": the expression (\x -> _) is first assigned the type Int -> Int when type-checking the containing expression (specifically, when type-checking iterate's arguments), and this type is then used to infer the type of x :: Int and of the hole _ :: Int.
In contrast, let and where-bound variables are typed "bottom-up". The type of next x = _ is inferred first, independently of its use in the main expression, and once that type has been determined, it's checked against its use in the expression iterate next 0. In this case, the expression next x = _ is inferred to have the rather useless type p -> t. Then, that type is checked against its use in the expression iterate next 0 which specializes it to Int -> Int (by taking p ~ Int and t ~ Int) and successfully type-checks.
In languages/type-systems without this distinction (and ignoring recursive bindings), a where clause is just syntactic sugar for a lambda binding and application:
foo = expr1 where baz = bazdefn ==> foo = (\baz -> expr1) bazdefn
so one thing you could do is "desugar" the where clause to the "equivalent" lambda binding:
foo' :: [Int]
foo' = (\next -> iterate next 0) (\x -> _)
This syntax is physically repulsive, sure, but it works. Because of the top-down typing of lambdas, both x and the hole are typed as Int.

Difference between -> and => symbols. What do they mean?

In Haskell, when we talk type declaration.
I've seen both -> and =>.
As an example: I can make my own type declaration.
addMe :: Int -> Int -> Int
addMe x y = x + y
And it works just fine.
But if we take a look at :t sqrt we get:
sqrt :: Floating a => a -> a
At what point do we use => and when do we use ->?
When do we use "fat arrow" and when do we use "thin arrow"?
-> is for explicit functions. I.e. when f is something that can be written in an expression of the form f x, the signature must have one of these arrows in it†. Specifically, the type of x (the argument) must appear to the left of a -> arrow.
It's best to not think of => as a function arrow at all, at least at first‡. It's an implication arrow in the logical sense: if a is a type with the property Floating a, then it follows that the signature of sqrt is a -> a.
For your addMe example, which is a function with two arguments, the signature must always have the form x -> y -> z. Possibly there can also be a q => in front of that; that doesn't influence the function-ishness, but may have some saying in what particular types are allowed. Generally, such constraints are not needed if the types are already fixed and concrete. Like, you could in principle impose a constraint on Int:
addMe :: Num Int => Int -> Int -> Int
addMe x y = x + y
...but that doesn't really accomplish anything, because everybody knows that the particular type Int is an instance of the Num class. Where you need such constraints is when the type is not fixed but a type variable (i.e. lowercase), i.e. if the function is polymorphic. You can't just write
addMe' :: a -> a -> a
addMe' x y = x + y
because that signature would suggest the function works for any type a whatsoever, but it can't work for all types (how would you add, for example, two strings? ok perhaps not the best example, but how would you multiply two strings?)
Hence you need the constraint
addMe' :: Num a => a -> a -> a
addMe' x y = x + y
This means, you don't care what exact type a is, but you do require it to be a numerical type. Anybody can use the function with their own type MyNumType, but they need to ensure that Num MyNumType is fulfilled: then it follows that addMe' can have signature MyNumType -> MyNumType -> MyNumType.
The way to ensure this is to either use a standard type which you know to be numerical, for instance addMe' 5.9 3.7 :: Double would work, or give an instance declaration for your custom type and the Num class. Only do the latter if you're sure it's a good idea; usually the standard num types are all you'll need.
†Note that the arrow may not be visible in the signature: it's possible to have a type synonym for a function type, for example when type IntEndofunc = Int -> Int, then f :: IntEndofunc; f x = x+x is ok. But you can think of the typedef as essentially just a syntactic wrapper; it's still the same type and does have the arrow in it.
‡It so happens that logical implication and function application can be seen as two aspects of the same mathematical concept. Furthermore, GHC actually implements class constraints as function arguments, so-called dictionaries. But all this happens behind the scenes, so if anything they're implicit functions. In standard Haskell, you will never see the LHS of a => type as the type of some actual argument the function is applied to.
The "thin arrow" is used for function types (t1 -> t2 being the type of a function that takes a value of type t1 and produces a value of type t2).
The "fat arrow" is used for type constraints. It separates the list of type constraints on a polymorphic function from the rest of the type. So given Floating a => a -> a, we have the function type a -> a, the type of a function that can take arguments of any type a and produces a result of that same type, with the added constraint Floating a, meaning that the function can in fact only be used with types that implement the Floating type class.
the -> is the constructor of functions and the => is used to constraints, a sort of "interface" in Haskell called typeclass.
A little example:
sum :: Int -> Int -> Int
sum x y = x + y
that function only allows Int types, but if you want a huge int or a small int, you probably want Integer, and how to tell it to use both?
sum2 :: Integral a => a -> a -> a
sum2 x y = x + y
now if you try to do:
sum2 3 1.5
it will give you an error
also, you may want to know if two data are equals, you want:
equals :: Eq a => a -> a -> Bool
equals x y = x == y
now if you do:
3 == 4
that's ok
but if you create:
data T = A | B
equals A B
it will give to you:
error:
• No instance for (Eq T) arising from a use of ‘equals’
• In the expression: equals A B
In an equation for ‘it’: it = equals A B
if you want for that to work, you must just do:
data T = A | B deriving Eq
equals A B
False

How do you apply function constraints in instance methods in Haskell?

I'm learning how to use typeclasses in Haskell.
Consider the following implementation of a typeclass T with a type constrained class function f.
class T t where
f :: (Eq u) => t -> u
data T_Impl = T_Impl_Bool Bool | T_Impl_Int Int | T_Impl_Float Float
instance T T_Impl where
f (T_Impl_Bool x) = x
f (T_Impl_Int x) = x
f (T_Impl_Float x) = x
When I load this into GHCI 7.10.2, I get the following error:
Couldn't match expected type ‘u’ with actual type ‘Float’
‘u’ is a rigid type variable bound by
the type signature for f :: Eq u => T_Impl -> u
at generics.hs:6:5
Relevant bindings include
f :: T_Impl -> u (bound at generics.hs:6:5)
In the expression: x
In an equation for ‘f’: f (T_Impl_Float x) = x
What am I doing/understanding wrong? It seems reasonable to me that one would want to specialize a typeclass in an instance by providing an accompaning data constructor and function implementation. The part
Couldn't match expected type 'u' with actual type 'Float'
is especially confusing. Why does u not match Float if u only has the constraint that it must qualify as an Eq type (Floats do that afaik)?
The signature
f :: (Eq u) => t -> u
means that the caller can pick t and u as wanted, with the only burden of ensuring that u is of class Eq (and t of class T -- in class methods there's an implicit T t constraint).
It does not mean that the implementation can choose any u.
So, the caller can use f in any of these ways: (with t in class T)
f :: t -> Bool
f :: t -> Char
f :: t -> Int
...
The compiler is complaining that your implementation is not general enough to cover all these cases.
Couldn't match expected type ‘u’ with actual type ‘Float’
means "You gave me a Float, but you must provide a value of the general type u (where u will be chosen by the caller)"
Chi has already pointed out why your code doesn't compile. But it's not even that typeclasses are the problem; indeed, your example has only one instance, so it might just as well be a normal function rather than a class.
Fundamentally, the problem is that you're trying to do something like
foobar :: Show x => Either Int Bool -> x
foobar (Left x) = x
foobar (Right x) = x
This won't work. It tries to make foobar return a different type depending on the value you feed it at run-time. But in Haskell, all types must be 100% determined at compile-time. So this cannot work.
There are several things you can do, however.
First of all, you can do this:
foo :: Either Int Bool -> String
foo (Left x) = show x
foo (Right x) = show x
In other words, rather than return something showable, actually show it. That means the result type is always String. It means that which version of show gets called will vary at run-time, but that's fine. Code paths can vary at run-time, it's types which cannot.
Another thing you can do is this:
toInt :: Either Int Bool -> Maybe Int
toInt (Left x) = Just x
toInt (Right x) = Nothing
toBool :: Either Int Bool -> Maybe Bool
toBool (Left x) = Nothing
toBool (Right x) = Just x
Again, that works perfectly fine.
There are other things you can do; without knowing why you want this, it's difficult to suggest others.
As a side note, you want to stop thinking about this like it's object oriented programming. It isn't. It requires a new way of thinking. In particular, don't reach for a typeclass unless you really need one. (I realise this particular example may just be a learning exercise to learn about typeclasses of course...)
It's possible to do this:
class Eq u => T t u | t -> u where
f :: t -> u
You need FlexibleContextx+FunctionalDepencencies and MultiParamTypeClasses+FlexibleInstances on call-site. Or to eliminate class and to use data types instead like Gabriel shows here

Wrapping / Unwrapping Universally Quantified Types

I have imported a data type, X, defined as
data X a = X a
Locally, I have defined a universally quantified data type, Y
type Y = forall a. X a
Now I need to define two functions, toY and fromY. For fromY, this definition works fine:
fromY :: Y -> X a
fromY a = a
but if I try the same thing for toY, I get an error
Couldn't match type 'a' with 'a0'
'a' is a rigid type variable bound by the type signature for 'toY :: X a -> y'
'a0' is a rigid type variable bound by the type signature for 'toY :: X a -> X a0'
Expected type: X a0
Actual type: X a
If I understand correctly, the type signature for toY is expanding to forall a. X a -> (forall a0. X a0) because Y is defined as a synonym, rather than a newtype, and so the two as in the definitions don't match up.
But if this is the case, then why does fromY type-check successfully? And is there any way around this problem other than using unsafeCoerce?
You claim to define an existential type, but you do not.
type Y = forall a. X a
defines a universally quantified type. For something to have type Y, it must have type X a for every a. To make an existentially quantified type, you always need to use data, and I find the GADT syntax easier to understand than the traditional existential one.
data Y where
Y :: forall a . X a -> Y
The forall there is actually optional, but I think clarifies things.
I'm too sleepy right now to work out your other questions, but I'll try again tomorrow if no one else does.
Remark:
This is more like a comment but I could not really put it there as it would have been unreadable; please forgive me this one time.
Aside from what dfeuer already told you, you might see (when you use his answer) that toY is now really easy to do but you might have trouble defining fromY – because you basically lose the type-information, so this will not work:
{-# LANGUAGE GADTs #-}
module ExTypes where
data X a = X a
data Y where
Y :: X a -> Y
fromY :: Y -> X a
fromY (Y a) = a
as here you have two different as – one from the constructor Y and one from X a – indeed if you strip the definition and try to compile: fromY (Y a) = a the compiler will tell you that the type a escapes:
Couldn't match expected type `t' with actual type `X a'
because type variable `a' would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor
Y :: forall a. X a -> Y,
in an equation for `fromY'
I think the only thing you will have left now will be something like this:
useY :: (forall a . X a -> b) -> Y -> b
useY f (Y x) = f x
but this might prove not to be too useful.
The thing is that you normally should constrain the forall a there a bit more (with type-classes) to get any meaningful behavior – but of course I cannot help here.
This wiki article might be interesting for you on the details.

What Justification for the type of f x = f x in Haskell is there?

Haskell gives f x = f x the type of t1 -> t, but could someone explain why?
And, is it possible for any other, nonequivalent function to have this same type?
Okay, starting from the function definition f x = f x, let's step through and see what we can deduce about the type of f.
Start with a completely unspecified type variable, a. Can we deduce more than that? Yes, we observe that f is a function taking one argument, so we can change a into a function between two unknown type variables, which we'll call b -> c. Whatever type b stands for is the type of the argument x, and whatever type c stands for must be the type of the right-hand side of the definition.
What can we figure out about the right-hand side? Well, we have f, which is a recursive reference to the function we're defining, so its type is still b -> c, where both type variables are the same as for the definition of f. We also have x, which is a variable bound within the definition of f and has type b. Applying f to x type checks, because they're sharing the same unknown type b, and the result is c.
At this point everything fits together and with no other restrictions, we can make the type variables "official", resulting in a final type of b -> c where both variables are the usual, implicitly universally quantified type variables in Haskell.
In other words, f is a function that takes an argument of any type and returns a value of any type. How can it return any possible type? It can't, and we can observe that evaluating it produces only an infinite recursion.
For the same reason, any function with the same type will be "equivalent" in the sense of never returning when evaluated.
An even more direct version is to remove the argument entirely:
foo :: a
foo = foo
...which is also universally quantified and represents a value of any type. This is pretty much equivalent to undefined.
f x = undefined
has the (alpha) equivalent type f :: t -> a.
If you're curious, Haskell's type system is derived from Hindley–Milner. Informally, the typechecker starts off with the most permissive types for everything, and unifies the various constraints until what remains is consistent (or not). In this case, the most general type is f :: t1 -> t, and there's no additional constraints.
Compare to
f x = f (f x)
which has inferred type f :: t -> t, due to unifying the types of the argument of f on the LHS and the argument to the outer f on the RHS.

Resources