Pattern matching on the result of type computing functions in idris - theorem-proving

Consider the following fragment:
import Data.List
%default total
x : Elem 1 [1, 2]
x = Here
type : Type
type = Elem 1 [1, 2]
y : type
y = Here
This gives the error:
When checking right hand side of y:
Type mismatch between
Elem x (x :: xs) (Type of Here)
and
iType (Expected type)
The type of y, when queried, is:
type : Type
-----------
y : type
Is it possible to force type to be evaluated during or before the type ascription of y, so that the type of y is Elem 1 [1, 2]?
My use case is that I want to be able to define generic predicates that return the right proposition terms for proofs, for example:
subset : List a -> List a -> Type
subset xs ys = (e : a) -> Elem e xs -> Elem e ys
thm_filter_subset : subset (filter p xs) xs

Names in type declarations which begin with a lower case letter are implicitly bound, so it's treating 'type' as a type parameter. You can either give 'type' a new name which begins with a capital (by convention this is what most people do in Idris) or you can explicitly qualify the name with the module it's in (Main, here).
Idris used to try guessing whether names such as 'type' were intended as an implicit or intended to refer to the global, as here. There's all kinds of voodoo involved in getting this right though, so it often failed, and so it now implements this much simpler rule. It's slightly annoying in cases such as this, but the alternative behaviour was more often annoying (and harder to explain).

Related

What are the rules of Coq implicit types deduction in Inductive definitions?

Consider this type that has X as an implicit type.
Inductive list' {X:Type} : Type :=
| nil'
| cons' (x : X) (l : list').
Coq deduced that type of the second argument of cons' is #list' A:
Fail Check cons' a (cons' b nil'). (* "cons' b nil'" expected to have type "#list' A"*)
But how was this type deduced unambiguously?
We can create another type:
Inductive list'' {X:Type} : Type :=
| nil''
| cons'' (x : X) (l : #list'' B).
Check cons'' a (cons'' b nil'').
It shows that l could also be #list' B.
To be precise, Coq inferred the type of cons' to be forall {X}, X -> #list' X -> #list' X. Then when you write cons a, Coq works out that you must be building a #list' A, and fills in X with A, thus constraining the second argument to be again of type #list' A.
However, the choice of X over some other type is not the only possible choice, as you noticed. In your second example, cons'' gets type forall {X}, X -> #list'' B -> #list'' X. However, when it is left unspecified, most people most of the time intend their parameters (things on the left side of the colon) to be uniform, that is, the same in the arguments as in the conclusion, which heuristic leads to the choice of X here. In general, Coq doesn't worry too much about making sure it's solutions are unique for things the user left unspecified.
In recent enough versions of Coq, you can use the option Uniform Inductive Parameters to specify that all parameters are uniform, or use a | to separate the uniform from the non-uniform parameters. In the case of lists, that would look like
Inductive list' (X:Type) | : Type :=
| nil'
| cons' (x : X) (l : list').
Note that with the |, in the declaration of constructors list' has type Type, while without the |, list' has type Type -> Type, and there is a constraint that the conclusion of the constructor has to be list X (while the arguments can use list other_type freely).

Questions about a la carte data types

I was reading the original paper about data types a la carte and decided to try to implement the idea in Scala (I know it's already implemented in many functional libraries). Unfortunately I found the original paper is hard to comprehend and I stuck somewhere in the beginning. Then I found another paper that was easier to understand and I managed to rewrite Haskell code from the paper into Scala, you can find it here. However I still struggling to understand a few moments:
A quote from the second paper
Orignal Expr data type
data Expr = Val Int | Add Expr Expr
New type signature:
data Arith e = Val Int | Add e e
For any functor f, its induced recursive datatype, Fix f, is defined as the least fixpoint of f, implemented as follows:
data Fix f = In (f (Fix f))
Now that we have tied the recursive knot of a signature,
Fix Arith is a language equivalent to the original Expr datatype
which allowed integer values and addition.
What does it mean exactly "we have tied the recursive knot of a signature" and what does it mean Fix Arith is a language equivalent to the original Expr ?
The actual type of In is In :: f (Fix f) -> Fix f
If we try to construct a value using In construct and Val 1 variable we'll get the following result:
> :t In(Val 1)
> In(Val 1) :: Fix Arith
Scala encoding of the same data types:
sealed trait Arith[A]
case class Val[A](x: Int) extends Arith[A]
case class Add[A](a: A, b: A) extends Arith[A]
trait Fix[F[_]]
case class In[F[_]](exp: F[Fix[F]]) extends Fix[F]
fold function
The fold function has the following signature and implementation
Haskell:
fold :: Functor f => (f a -> a) -> Fix f -> a
fold f (In t) = f (fmap (fold f) t)
Scala variant I came up with
def fold[F[_] : Functor, A](f: F[A] => A): Fix[F] => A = {
case In(t) =>
val g: F[Fix[F]] => F[A] = implicitly[Functor[F]].lift(fold(f))
f(g(t))
}
The thing that I'm curious about is that in my Scala version function g has the following type F[Fix[F]] => F[A] but the type of variable t after pattern matching is LaCarte$Add with value Add(In(Val(1)),In(Val(2))), how it happens that it's valid to apply function g to LaCarte$Add ? Also, I'd very appreciate if you can help me to understand fold function ?
Quote from the paper:
The first argument of fold is an f-algebra, which provides
the behavior of each constructor associated with a given signature f.
What does it mean exactly “we have tied the ‘recursive knot’ of a signature”?
The original Expr datatype is recursive, referring to itself in its own definition:
data Expr = Val Int | Add Expr Expr
The Arith type “factors out” the recursion by replacing recursive calls with a parameter:
data Arith e = Val Int | Add e e
The original Expr type can have any depth of nesting, which we want to support with Arith as well, but the maximum depth depends on what type we choose for e:
Arith Void can’t be nested: it can only be a literal value (Val n) because we can’t construct an Add, because we can’t obtain a value of type Void (it has no constructors)
Arith (Arith Void) can have one level of nesting: the outer constructor can be an Add, but the inner constructors can only be Lit.
Arith (Arith (Arith Void)) can have two levels
And so on
What Fix Arith gives us is a way to talk about the fixed point Arith (Arith (Arith …)) with no limit on the depth.
This is just like how we can replace a recursive function with a non-recursive function and recover the recursion with the fixed-point combinator:
factorial' :: (Integer -> Integer) -> Integer -> Integer
factorial' recur n = if n <= 1 then 1 else n * recur (n - 1)
factorial :: Integer -> Integer
factorial = fix factorial'
factorial 5 == 120
What does it mean Fix Arith is a language equivalent to the original Expr?
The language (grammar) that Fix Arith represents is equivalent to the language that Expr represents; that is, they’re isomorphic: you can write a pair of total functions Fix Arith -> Expr and Expr -> Fix Arith.
How it happens that it’s valid to apply function g to LaCarte$Add?
I’m not very familiar with Scala, but it looks like Add is a subtype of Arith, so the parameter of g of type F[Fix[F]] can be filled with a value of type Arith[Fix[Arith]] which you get by matching on the In constructor to “unfold” one level of recursion.

What kind of morphism is `filter` in category theory?

In category theory, is the filter operation considered a morphism? If yes, what kind of morphism is it? Example (in Scala)
val myNums: Seq[Int] = Seq(-1, 3, -4, 2)
myNums.filter(_ > 0)
// Seq[Int] = List(3, 2) // result = subset, same type
myNums.filter(_ > -99)
// Seq[Int] = List(-1, 3, -4, 2) // result = identical than original
myNums.filter(_ > 99)
// Seq[Int] = List() // result = empty, same type
One interesting way of looking at this matter involves not picking filter as a primitive notion. There is a Haskell type class called Filterable which is aptly described as:
Like Functor, but it [includes] Maybe effects.
Formally, the class Filterable represents a functor from Kleisli Maybe to Hask.
The morphism mapping of the "functor from Kleisli Maybe to Hask" is captured by the mapMaybe method of the class, which is indeed a generalisation of the homonymous Data.Maybe function:
mapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
The class laws are simply the appropriate functor laws (note that Just and (<=<) are, respectively, identity and composition in Kleisli Maybe):
mapMaybe Just = id
mapMaybe (g <=< f) = mapMaybe g . mapMaybe f
The class can also be expressed in terms of catMaybes...
catMaybes :: Filterable f => f (Maybe a) -> f a
... which is interdefinable with mapMaybe (cf. the analogous relationship between sequenceA and traverse)...
catMaybes = mapMaybe id
mapMaybe g = catMaybes . fmap g
... and amounts to a natural transformation between the Hask endofunctors Compose f Maybe and f.
What does all of that have to do with your question? Firstly, a functor is a morphism between categories, and a natural transformation is a morphism between functors. That being so, it is possible to talk of morphisms here in a sense that is less boring than the "morphisms in Hask" one. You won't necessarily want to do so, but in any case it is an existing vantage point.
Secondly, filter is, unsurprisingly, also a method of Filterable, its default definition being:
filter :: Filterable f => (a -> Bool) -> f a -> f a
filter p = mapMaybe $ \a -> if p a then Just a else Nothing
Or, to spell it using another cute combinator:
filter p = mapMaybe (ensure p)
That indirectly gives filter a place in this particular constellation of categorical notions.
To answer are question like this, I'd like to first understand what is the essence of filtering.
For instance, does it matter that the input is a list? Could you filter a tree? I don't see why not! You'd apply a predicate to each node of the tree and discard the ones that fail the test.
But what would be the shape of the result? Node deletion is not always defined or it's ambiguous. You could return a list. But why a list? Any data structure that supports appending would work. You also need an empty member of your data structure to start the appending process. So any unital magma would do. If you insist on associativity, you get a monoid. Looking back at the definition of filter, the result is a list, which is indeed a monoid. So we are on the right track.
So filter is just a special case of what's called Foldable: a data structure over which you can fold while accumulating the results in a monoid. In particular, you could use the predicate to either output a singleton list, if it's true; or an empty list (identity element), if it's false.
If you want a categorical answer, then a fold is an example of a catamorphism, an example of a morphism in the category of algebras. The (recursive) data structure you're folding over (a list, in the case of filter) is an initial algebra for some functor (the list functor, in this case), and your predicate is used to define an algebra for this functor.
In this answer, I will assume that you are talking about filter on Set (the situation seems messier for other datatypes).
Let's first fix what we are talking about. I will talk specifically about the following function (in Scala):
def filter[A](p: A => Boolean): Set[A] => Set[A] =
s => s filter p
When we write it down this way, we see clearly that it's a polymorphic function with type parameter A that maps predicates A => Boolean to functions that map Set[A] to other Set[A]. To make it a "morphism", we would have to find some categories first, in which this thing could be a "morphism". One might hope that it's natural transformation, and therefore a morphism in the category of endofunctors on the "default ambient category-esque structure" usually referred to as "Hask" (or "Scal"? "Scala"?). To show that it's natural, we would have to check that the following diagram commutes for every f: B => A:
- o f
Hom[A, Boolean] ---------------------> Hom[B, Boolean]
| |
| |
| |
| filter[A] | filter[B]
| |
V ??? V
Hom[Set[A], Set[A]] ---------------> Hom[Set[B], Set[B]]
however, here we fail immediately, because it's not clear what to even put on the horizontal arrow at the bottom, since the assignment A -> Hom[Set[A], Set[A]] doesn't even seem functorial (for the same reasons why A -> End[A] is not functorial, see here and also here).
The only "categorical" structure that I see here for a fixed type A is the following:
Predicates on A can be considered to be a partially ordered set with implication, that is p LEQ q if p implies q (i.e. either p(x) must be false, or q(x) must be true for all x: A).
Analogously, on functions Set[A] => Set[A], we can define a partial order with f LEQ g whenever for each set s: Set[A] it holds that f(s) is subset of g(s).
Then filter[A] would be monotonic, and therefore a functor between poset-categories. But that's somewhat boring.
Of course, for each fixed A, it (or rather its eta-expansion) is also just a function from A => Boolean to Set[A] => Set[A], so it's automatically a "morphism" in the "Hask-category". But that's even more boring.
filter can be written in terms of foldRight as:
filter p ys = foldRight(nil)( (x, xs) => if (p(x)) x::xs else xs ) ys
foldRight on lists is a map of T-algebras (where here T is the List datatype functor), so filter is a map of T-algebras.
The two algebras in question here are the initial list algebra
[nil, cons]: 1 + A x List(A) ----> List(A)
and, let's say the "filter" algebra,
[nil, f]: 1 + A x List(A) ----> List(A)
where f(x, xs) = if p(x) x::xs else xs.
Let's call filter(p, _) the unique map from the initial algebra to the filter algebra in this case (it is called fold in the general case). The fact that it is a map of algebras means that the following equations are satisfied:
filter(p, nil) = nil
filter(p, x::xs) = f(x, filter(p, xs))

Are Coercions allowed within polymorphic datatypes in coq?

I'm using a lot of pairs with types that would normally be coerced freely. However, the notation doesn't explicitly provide the types for the pairs, even though the context does. The following code provides a simple MWE of the principle:
Coercion nat_to_bool (n : nat) : bool :=
match n with
| 0 => false
| _ => true
end.
Inductive newtype : Type :=
| firstconstr : bool -> newtype
| secondconstr : (bool * bool) -> newtype.
Check (3 : bool).
Check (firstconstr 3).
Fail Check (secondconstr (3, true)).
Check (secondconstr (#pair bool bool 3 true)).
The failure message is The term "(3, true)" has type "(nat * bool)%type" while it is expected to have type "(bool * bool)%type". Obviously the type system can figure out the type that it is supposed to be, but can't decide to coerce the value properly.
Is there a way to declare the coercion in such a way that tuples (and other polymorphic data types with inferred types) are coerced properly?
Maybe you can make a notation that desugars to an annotation so the coercion goes through, assuming the pair is always constructed explicitly (that seems fair for a typing judgement G |- x : T where x : T is a pair, although I think the whole judgement is more commonly seen as a triple).
Here's a PoC with the minimal example:
Notation "'secondconstr'' ( x , y )" := (secondconstr (x : bool, y)).
Check (secondconstr' (3, true)).
And in the context of your types judgement, it might look like this:
Notation "Gamma |- v : T" := (types Gamma (v : value, T))
(at level 100).

Gentle Intro to Haskell: " .... there is no single type that contains both 2 and 'b'." Can I not make such a type ?

I am currently learning Haskell, so here are a beginner's questions:
What is meant by single type in the text below ?
Is single type a special Haskell term ? Does it mean atomic type here ?
Or does it mean that I can never make a list in Haskell in which I can put both 1 and 'c' ?
I was thinking that a type is a set of values.
So I cannot define a type that contains Chars and Ints ?
What about algebraic data types ?
Something like: data IntOrChar = In Int | Ch Char ? (I guess that should work but I am confused what the author meant by that sentence.)
Btw, is that the only way to make a list in Haskell in which I can put both Ints and Chars? Or is there a more tricky way ?
A Scala analogy: in Scala it would be possible to write implicit conversions to a type that represents both Ints and Chars (like IntOrChar) and then it would be possible to put seemlessly Ints and Chars into List[IntOrChar], is that not possible with Haskell ? Do I always have to explicitly wrap every Int or Char into IntOrChar if I want to put them into a list of IntOrChar ?
From Gentle Intro to Haskell:
Haskell also incorporates polymorphic types---types that are
universally quantified in some way over all types. Polymorphic type
expressions essentially describe families of types. For example,
(forall a)[a] is the family of types consisting of, for every type a,
the type of lists of a. Lists of integers (e.g. [1,2,3]), lists of
characters (['a','b','c']), even lists of lists of integers, etc., are
all members of this family. (Note, however, that [2,'b'] is not a
valid example, since there is no single type that contains both 2 and
'b'.)
Short answer.
In Haskell there are no implicit conversions. Also there are no union types - only disjoint unions(which are algebraic data types). So you can only write:
someList :: [IntOrChar]
someList = [In 1, Ch 'c']
Longer and certainly not gentle answer.
Note: This is a technique that's very rarely used. If you need it you're probably overcomplicating your API.
There are however existential types.
{-# LANGUAGE ExistentialQuantification, RankNTypes #-}
class IntOrChar a where
intOrChar :: a -> Either Int Char
instance IntOrChar Int where
intOrChar = Left
instance IntOrChar Char where
intOrChar = Right
data List = Nil
| forall a. (IntOrChar a) => Cons a List
someList :: List
someList = (1 :: Int) `Cons` ('c' `Cons` Nil)
Here I have created a typeclass IntOrChar with only function intOrChar. This way you can convert anything of type forall a. (IntOrChar a) => a to Either Int Char.
And also a special kind of list that uses existential type in its second constructor.
Here type variable a is bound(with forall) at the constructor scope. Therefore every time
you use Cons you can pass anything of type forall a. (IntOrChar a) => a as a first argument. Consequently during a destruction(i.e. pattern matching) the first argument will
still be forall a. (IntOrChar a) => a. The only thing you can do with it is either pass it on or call intOrChar on it and convert it to Either Int Char.
withHead :: (forall a. (IntOrChar a) => a -> b) -> List -> Maybe b
withHead f Nil = Nothing
withHead f (Cons x _) = Just (f x)
intOrCharToString :: (IntOrChar a) => a -> String
intOrCharToString x =
case intOrChar of
Left i -> show i
Right c -> show c
someListHeadString :: Maybe String
someListHeadString = withHead intOrCharToString someList
Again note that you cannot write
{- Wont compile
safeHead :: IntOrChar a => List -> Maybe a
safeHead Nil = Nothing
safeHead (Cons x _) = Just x
-}
-- This will
safeHead2 :: List -> Maybe (Either Int Char)
safeHead2 Nil = Nothing
safeHead2 (Cons x _) = Just (intOrChar x)
safeHead will not work because you want a type of IntOrChar a => Maybe a with a bound at safeHead scope and Just x will have a type of IntOrChar a1 => Maybe a1 with a1 bound at Cons scope.
In Scala there are types that include both Int and Char such as AnyVal and Any, which are both supertypes of Char and Int. In Haskell there is no such hierarchy, and all the basic types are disjoint.
You can create your own union types which describe the concept of 'either an Int or a Char (or you could use the built-in Either type), but there are no implicit conversions in Haskell to transparently convert an Int into an IntOrChar.
You could emulate the concept of 'Any' using existential types:
data AnyBox = forall a. (Show a, Hashable a) => AB a
heteroList :: [AnyBox]
heteroList = [AB (1::Int), AB 'b']
showWithHash :: AnyBox -> String
showWithHash (AB v) = show v ++ " - " ++ (show . hash) v
let strs = map showWithHash heteroList
Be aware that this pattern is discouraged however.
I think that the distinction that is being made here is that your algebraic data type IntOrChar is a "tagged union" - that is, when you have a value of type IntOrChar you will know if it is an Int or a Char.
By comparison consider this anonymous union definition (in C):
typedef union { char c; int i; } intorchar;
If you are given a value of type intorchar you don't know (apriori) which selector is valid. That's why most of the time the union constructor is used in conjunction with a struct to form a tagged-union construction:
typedef struct {
int tag;
union { char c; int i; } intorchar_u
} IntOrChar;
Here the tag field encodes which selector of the union is valid.
The other major use of the union constructor is to overlay two structures to get an efficient mapping between sub-structures. For example, this union is one way to efficiently access the individual bytes of a int (assuming 8-bit chars and 32-bit ints):
union { char b[4]; int i }
Now, to illustrate the main difference between "tagged unions" and "anonymous unions" consider how you go about defining a function on these types.
To define a function on an IntOrChar value (the tagged union) I claim you need to supply two functions - one which takes an Int (in the case that the value is an Int) and one which takes a Char (in case the value is a Char). Since the value is tagged with its type, it knows which of the two functions it should use.
If we let F(a,b) denote the set of functions from type a to type b, we have:
F(IntOrChar,b) = F(Int,b) \times F(Char,b)
where \times denotes the cross product.
As for the anonymous union intorchar, since a value doesn't encode anything bout its type the only functions which can be applied are those which are valid for both Int and Char values, i.e.:
F(intorchar,b) = F(Int,b) \cap F(Char,b)
where \cap denotes intersection.
In Haskell there is only one function (to my knowledge) which can be applied to both integers and chars, namely the identity function. So there's not much you could do with a list like [2, 'b'] in Haskell. In other languages this intersection may not be empty, and then constructions like this make more sense.
To summarize, you can have integers and characters in the same list if you create a tagged-union, and in that case you have to tag each of the values which will make you list look like:
[ I 2, C 'b', ... ]
If you don't tag your values then you are creating something akin to an anonymous union, but since there aren't any (useful) functions which can be applied to both integers and chars there's not really anything you can do with that kind of union.