Unify a generic type variable to another existing type - type-inference

There's a line from Elm guide below:
Task.perform AdjustTimeZone Time.here
I've found the following type signatures:
-- ∵
AdjustTimeZone : Zone -> Msg
here : Task x Zone
perform : (a -> msg) -> Task Never a -> Cmd msg
-- ∴
perform AdjustTimeZone here : Cmd Msg
How could Task x Zone be unified to Task Never a? Especially, x to Never is doubtful while Zone to a reasonable.

I'm no type inference expert, but I don't think it's correct to say that "x unifies to Never" and suspect this is the source of your confusion. x and a are both type variables which will unify either way unless there are other constraints that come into conflict. So just as a becomes Zone, x becomes Never, not the other way around.
You might also wonder why Time.here has the type Task x Zone rather than Task Never Zone since, after all, it's here that should know whether or not it can error. I think this is because 1) it doesn't matter (to the type system, though it certainly might for the user), and 2) it makes it more easily composable.
So let's say you want to sequence Time.here with some other Task that can error. Task.andThen has the type (a -> Task x b) -> Task x a -> Task x b with the x (error) type variable being the same in all Tasks. So if Time.heres type was Task Never Zone, we'd have to supply andThen with a function Zone -> Task Never b. And that obvosuly won't work.
I'm pretty sure you could just do TasK.here |> Task.mapError never |> Task.andThen (\zone -> ...), but this isn't really necessary if the error type is left a type variable rather than be constrained to Never. And that isn't a problem since Task.here won't produce any xs, so it doesn't matter what it unifies as.

Related

Where is the Idris == operator useful?

As a beginner in type-driven programming, I'm curious about the use of the == operator. Examples demonstrate that it's not sufficient to prove equality between two values of a certain type, and special equality checking types are introduced for the particular data types. In that case, where is == useful at all?
(==) (as the single constituent function of the Eq interface) is a function from a type T to Bool, and is good for equational reasoning. Whereas x = y (where x : T and y : T) AKA "intensional equality" is itself a type and therefore a proposition. You can and often will want to bounce back and forth between the two different ways of expressing equality for a particular type.
x == y = True is also a proposition, and is often an intermediate step between reasoning about (==) and reasoning about =.
The exact relationship between the two types of equality is rather complex, and you can read https://github.com/pdorrell/learning-idris/blob/9d3454a77f6e21cd476bd17c0bfd2a8a41f382b7/finished/EqFromEquality.idr for my own attempt to understand some aspects of it. (One thing to note is that even though an inductively defined type will have decideable intensional equality, you still have to go through a few hoops to prove that, and a few more hoops to define a corresponding implementation of Eq.)
One particular handy code snippet is this:
-- for rel x y, provide both the computed value, and the proposition that it is equal to the value (as a dependent pair)
has_value_dpair : (rel : t -> t -> Bool) -> (x : t) -> (y : t) -> (value: Bool ** rel x y = value)
has_value_dpair rel x y = (rel x y ** Refl)
You can use it with the with construct when you have a value returned from rel x y and you want to reason about the proposition rel x y = True or rel x y = False (and rel is some function that might represent a notion of equality between x and y).
(In this answer I assume the case where (==) corresponds to =, but you are entirely free to define a (==) function that doesn't correspond to =, eg when defining a Setoid. So that's another reason to use (==) instead of =.)
You still need good old equality because sometimes you can't prove things. Sometimes you don't even need to prove. Consider next example:
countEquals : Eq a => a -> List a -> Nat
countEquals x = length . filter (== x)
You might want to just count number of equal elements to show some statistics to user. Another example: tests. Yes, even with strong type system and dependent types you might want to perform good old unit tests. So you want to check for expectations and this is rather convenient to do with (==) operator.
I'm not going to write full list of cases where you might need (==). Equality operator is not enough for proving but you don't always need proofs.

How to "read" Elm's -> operator

I'm really loving Elm, up to the point where I encounter a function I've never seen before and want to understand its inputs and outputs.
Take the declaration of foldl for example:
foldl : (a -> b -> b) -> b -> List a -> b
I look at this and can't help feeling as if there's a set of parentheses that I'm missing, or some other subtlety about the associativity of this operator (for which I can't find any explicit documentation). Perhaps it's just a matter of using the language more until I just get a "feel" for it, but I'd like to think there's a way to "read" this definition in English.
Looking at the example from the docs…
foldl (::) [] [1,2,3] == [3,2,1]
I expect the function signature to read something like this:
Given a function that takes an a and a b and returns a b, an additional b, and a List, foldl returns a b.
Is that correct?
What advice can you give to someone like me who desperately wants inputs to be comma-delineated and inputs/outputs to be separated more clearly?
Short answer
The missing parentheses you're looking for are due to the fact that -> is right-associative: the type (a -> b -> b) -> b -> List a -> b is equivalent to (a -> b -> b) -> (b -> (List a -> b)). Informally, in a chain of ->s, read everything before the last -> as an argument and only the rightmost thing as a result.
Long answer
The key insight you may be missing is currying -- the idea that if you have a function that takes two arguments, you can represent it with a function that takes the first argument and returns a function that takes the second argument and then returns the result.
For instance, suppose you have a function add that takes two integers and adds them together. In Elm, you could write a function that takes both elements as a tuple and adds them:
add : (Int, Int) -> Int
add (x, y) = x+y
and you could call it as
add (1, 2) -- evaluates to 3
But suppose you didn't have tuples. You might think that there would be no way to write this function, but in fact using currying you could write it as:
add : Int -> (Int -> Int)
add x =
let addx : Int -> Int
addx y = x+y
in
addx
That is, you write a function that takes x and returns another function that takes y and adds it to the original x. You could call it with
((add 1) 2) -- evaluates to 3
You can now think of add in two ways: either as a function that takes an x and a y and adds them, or as a "factory" function that takes x values and produces new, specialized addx functions that take just one argument and add it to x.
The "factory" way of thinking about things comes in handy every once in a while. For instance, if you have a list of numbers called numbers and you want to add 3 to each number, you can just call List.map (add 3) numbers; if you'd written the tuple version instead you'd have to write something like List.map (\y -> add (3,y)) numbers which is a bit more awkward.
Elm comes from a tradition of programming languages that really like this way of thinking about functions and encourage it where possible, so Elm's syntax for functions is designed to make it easy. To that end, -> is right-associative: a -> b -> c is equivalent to a -> (b -> c). This means if you don't parenthesize, what you're defining is a function that takes an a and returns a b -> c, which again we can think of either as a function that takes an a and a b and returns a c, or equivalently a function that takes an a and returns a b -> c.
There's another syntactic nicety that helps call these functions: function application is left-associative. That way, the ugly ((add 1) 2) from above can be written as add 1 2. With that syntax tweak, you don't have to think about currying at all unless you want to partially apply a function -- just call it with all the arguments and the syntax will work out.

Example of a `Type 1` that is neither `Type` nor an inhabitant of `Type`

What is an example of an inhabitant of Type 1 that is neither Type nor an inhabitant of Type? I wasn't able to come up with anything while exploring in the Idris REPL.
To be more precise, I'm looking for some x other than Type that yields the following:
Idris> :t x
x : Type 1
I'm not a type theory specialist, but here is my understanding. In the Idris tutorial there is a section 12.8 Cumulativity. It says that there is an internal hierarchy of type universes:
Type : Type 1 : Type 2 : Type 3 : ...
And for any x : Type n implies x : Type m for any m > n. There is also an example demonstrating how it prevents possible cycles in the type inference.
But I think that this hierarchy is only for internal use and there is no possibility to create a value of Type (n+1) which is not in Type n.
See also articles in nLab about universes in type theory and about type of types.
Maybe this issue in the idris-dev repository can be useful too. Edwin Brady refers there to the Design and Implementation paper (see section 3.2.2).
I'm not an Idris expert, but I'd expect that
Type -> Type
is also in Type 1.
I'd also expect
Nat -> Type
and if you're very lucky (not so sure about this one)
List Type
to be that large.
The idea is that you can do all type-building operations at every level. Each time you use types from one level as values, the types of those structures live one level up.

How to deal with this error?

I'm dealing with very long lists, and large trees.
Sometimes I would find this error:
surgery a;;
Characters 8-9:
surgery a;;
^
Error: This expression has type int t/1044
but an expression was expected of type 'a t/1810
# type 'a t = | Leaf of ('a -> 'a -> int)
| Node of 'a * 'a t * 'a t * ('a -> 'a -> int)
I'm not sure about what type is that kind of error, but I guess it's some kind of an overflow. The type matches correctly but there are large numbers after the backslash that follows the type. In this case 1044 and 1810.
This time I have run some code before surgery a. If I kill the current top-level and start over, surgery a would run.
My questions are:
1. What is this error exactly?
2. When and how does it occur?
3. Why rerunning it from a new top-level would make it work?
4. How should I deal with it?
This is a type error, not a runtime error. It does not "cost" anything and is not in any way related to the size of the structures you have in memory.
It happens if you're not careful in the toplevel, and mix two different types with the same name. Compare:
type t = int;;
let f (x : t) = ();;
type u = bool;;
let g (y : u) = f y;;
^
Error: This expression has type u = bool
but an expression was expected of type t = int
with
type t = int;;
let f (x : t) = ();;
type t = bool;;
let g (y : t) = f y;;
^
Error: This expression has type t/1047 = bool
but an expression was expected of type t/1044 = int
This is the exact same typing error happening in both cases: you mixed different types. But in the second case, both have the same name t. The type-system tries to be helpful and tells you about the unique integers it internally assign to names, to make sure there are really unique throughout the program.
This kind of error cannot happen outside the toplevel (when compiling a program the usual way), as it is not possible to define two types with the same name at the exact same path.
How to fix it: if you redefine a type with a new definition that is not equivalent to the previous one, you must be careful to also redefine the operations on this previous type previously recorded in the toplevel. Indeed, they are still typed as expecting the old type, and using them with the new type will result in such errors.

Test.QuickCheck: speed up testing multiple properties for the same type

I am testing a random generator generating instances of my own type. For that I have a custom instance of Arbitrary:
complexGenerator :: (RandomGen g) => g -> (MyType, g)
instance Arbitrary MyType where
arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary
This works well with Test.QuickCheck (actually, Test.Framework) for testing that the generated values hold certain properties. However, there are quite a few properties I want to check, and the more I add, the more time it takes to verify them all.
Is there a way to use the same generated values for testing every property, instead of generating them anew each time? I obviously still want to see, on failures, which property did not hold, so making one giant property with and is not optimal.
I obviously still want to see, on failures, which property did not hold, so making one giant property with and is not optimal.
You could label each property using printTestCase before making a giant property with conjoin.
e.g. you were thinking this would be a bad idea:
prop_giant :: MyType -> Bool
prop_giant x = and [prop_one x, prop_two x, prop_three x]
this would be as efficient yet give you better output:
prop_giant :: MyType -> Property
prop_giant x = conjoin [printTestCase "one" $ prop_one x,
printTestCase "two" $ prop_two x,
printTestCase "three" $ prop_three x]
(Having said that, I've never used this method myself and am only assuming it will work; conjoin is probably marked as experimental in the documentation for a reason.)
In combination with the voted answer, what I've found helpful is using a Reader transformer with the Writer monad:
type Predicate r = ReaderT r (Writer String) Bool
The Reader "shared environment" is the tested input in this case. Then you can compose properties like this:
inv_even :: Predicate Int
inv_even = do
lift . tell $ "this is the even invariant"
(==) 0 . flip mod 2 <$> ask
toLabeledProp :: r -> Predicate r -> Property
toLabeledProp cause r =
let (effect, msg) = runWriter . (runReaderT r) $ cause in
printTestCase ("inv: " ++ msg) . property $ effect
and combining:
fromPredicates :: [Predicate r] -> r -> Property
fromPredicates predicates cause =
conjoin . map (toLabeledProp cause) $ predicates
I suspect there is another approach involving something similar to Either or a WriterT here- which would concisely compose predicates on different types into one result. But at the least, this allows for documenting properties which impose different post-conditions dependent on the the value of the input.
Edit: This idea spawned a library:
http://github.com/jfeltz/quickcheck-property-comb