Create a zero length vector - idris

Given this type for vectors, what's the way to create a zero length vector of a particular type of items?
data Vect : Nat -> Type -> Type where
VectNil : Vect 0 ty
(::) : ty -> Vect size ty -> Vect (S size) ty
VectNil String and all the variations I've tried in the REPL failed.
Is it not correct to expect VectNil to work like the default constructor of the generic List in C# does?
new List<string> (); // creates a zero length List of string

VecNil is value constructor and it accepts implicit type parameter. Here you can see it in REPL:
*x> :set showimplicits
*x> :t VectNil
Main.VectNil : {ty : Type} -> Main.Vect 0 ty
Idris infers values of those implicit parameters from the context. But sometimes context does not have enough information:
*x> VectNil
(input):Can't infer argument ty to Main.VectNil
You can explicitly provide value for implicit parameter using braces:
*x> VectNil {ty=String}
Main.VectNil {ty = String} : Main.Vect 0 String
Or use the the operator to add a type annotation:
*x> the (Vect 0 String) VectNil
Main.VectNil : Main.Vect 0 String
In larger programs, Idris is able to infer the type based on its use site.

Related

Is there a notion of "heterogenous collection of a given shape"?

A common pattern in functional programming languages with a sufficiently advanced type system to to have a type of "heterogeneous lists". For instance, given a list defined as:
data List a = Nil | Cons a (List a)
(Note: For concreteness, I will use Idris in this question, but this could also be answered in Haskell (with the right extensions), Agda, etc...)
We can define HList:
data HList : List a -> Type where
Nil : HList []
(::) : a -> HList as -> HList (a :: as)
This is a list which holds a different type (specified by the type-level List a) at each "position" of the List data type. This made me wonder: Can we generalize this construction? For instance, given a simple tree-like structure:
data Tree a = Branch a [Tree a]
Does it make sense to define a heterogenous tree?
where HTree : Tree a -> Type where
...
More generally in a dependently-typed language, is it possible to define a general construction:
data Hetero : (f : Type -> Type) -> f a -> Type where
....
that takes a data type of kind Type -> Type and returns the "heterogeneous container" of shape f? Has anyone made use of this construction before if possible?
We can talk about the shape of any functor using map and propositional equality. In Idris 2:
Hetero : (f : Type -> Type) -> Functor f => f Type -> Type
Hetero f tys = (x : f (A : Type ** A) ** map fst x = tys)
The type (A : Type ** A) is the type of non-empty types, in other words, values of arbitrary type. We get heterogeneous collections by putting arbitrarily typed values into functors, then constraining the types elementwise to particular types.
Some examples:
ex1 : Hetero List [Bool, Nat, Bool]
ex1 = ([(_ ** True), (_ ** 10), (_ ** False)] ** Refl)
data Tree : Type -> Type where
Leaf : a -> Tree a
Node : Tree a -> Tree a -> Tree a
Functor Tree where
map f (Leaf a) = Leaf (f a)
map f (Node l r) = Node (map f l) (map f r)
ex2 : Hetero Tree (Node (Leaf Bool) (Leaf Nat))
ex2 = (Node (Leaf (_ ** False)) (Leaf (_ ** 10)) ** Refl)

How to use data from Maybe as Vect size variable

I'm trying to write a simple program that asks the user about the list size and shows content from that list by index also by the user's input. But I've stuck. I have a function that builds a list by a number. Now I want to create another function that uses Maybe Nat as input and returns Maybe (Vect n Nat). But I have no idea how to accomplish this. Here is the code:
module Main
import Data.Fin
import Data.Vect
import Data.String
getList: (n: Nat) -> Vect n Nat
getList Z = []
getList (S k) = (S k) :: getList k
mbGetList : (Maybe Nat) -> Maybe (Vect n Nat)
mbGetList mbLen = case mbLen of
Just len => Just (getList len)
Nothing => Nothing
main : IO ()
main = do
len <- readNum
-- list <- mbGetList len
putStrLn (show len)
And here is the error:
|
55 | Just len => Just (getList len)
| ~~~~~~~~~~~
When checking right hand side of Main.case block in mbGetList at main.idr:54:24-28 with expected type
Maybe (Vect n Nat)
When checking argument n to function Main.getList:
Type mismatch between
n (Inferred value)
and
len (Given value)
I've tried to declare an implicit variable. The code compiles, but I can't use it (at least throw repl). Also, I've tried to use dependant pair and also failed. Maybe I should use Dec instead of Maybe? But how??? Another attempt was a try to use map function. But in that case, I have an error like that: Can't infer argument n to Functor.
So, what I've missed?
This answer doesn't feel optimal, but here goes
mbGetList : (mbLen: Maybe Nat) -> case mbLen of
(Just len) => Maybe (Vect len Nat)
Nothing => Maybe (Vect Z Nat)
mbGetList (Just len) = Just (getList len)
mbGetList Nothing = Nothing
I think the difficulty comes from the fact that there's no well-defined length for the Vect if you don't have a valid input

Trying to bring implicit argument into scope on the left side of a definition in Idris results in "is f applied to too many arguments" error

The function applyRule is supposed to extract the implicit argument n that is used in another arguments it gets, of type VVect.
data IVect : Vect n ix -> (ix -> Type) -> Type where -- n is here
Nil : IVect Nil b
(::) : b i -> IVect is b -> IVect (i :: is) b
VVect : Vect n Nat -> Type -> Type -- also here
VVect is a = IVect is (flip Vect a)
-- just for completeness
data Expression = Sigma Nat Expression
applyRule : (signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n
Without referring to {n}, the code type-checks (if cast n is changed to some valid double). Adding it in, however, results in the following error:
When checking left hand side of applyRule:
Type mismatch between
Double (Type of applyRule signals params sigmas rule)
and
_ -> _ (Is applyRule signals
params
sigmas
rule applied to too many arguments?)
This doesn't seem to make sense to me, because I'm not pattern-matching on any parameter that could have a dependency on n, so I thought that simply putting it in curly braces would bring it into scope.
You can only bring n into scope if it is defined somewhere (e.g. as a variable in the arguments). Otherwise it would be hard to figure out where the n comes from – at least for a human.
applyRule : {is : Vect n Nat} ->
(signals : VVect is Double) ->
(params : List Double) ->
(sigmas : List Double) ->
(rule : Expression) ->
Double
applyRule {n} signals params sigmas (Sigma k expr1) = cast n

Type constructor with no parameters causing "Can't infer argument" error

I defined a type like this:
data MyList a = Empty | Cons a (MyList a)
In Haskell, an empty MyList can be instantiated with Empty, but Idris complains:
> Empty
(input):Can't infer argument a to Empty
Why is that?
:set showimplicits in the REPL helps when debugging error messages:
>:set showimplicits
>:t Empty
Main.Empty : {a : Type} -> Main.MyList a
As you can see, the type constructor has an argument and it can't infer it. If you call a function (like Empty is one), Idris tries to infer values for all implicit arguments. If a can be inferred from the context, for example by using the (MyList Nat) Empty, it works.
If you are explicit about the argument, it works too (and you can see a distinction between Haskell and Idris):
data MyList : Type -> Type where
Empty : (a : Type) -> MyList a
Cons : (a : Type) -> (x : a) -> MyList a -> MyList a
>Empty
Empty : (a : Type) -> MyList a
Idris' a is explicit, while in Haskell the unbound type parameter is hidden: Empty :: MyList a.

Evaluating `IO` Actions from REPL

Given:
*lecture2> :let x = (the (IO Int) (pure 42))
Looking at its type, what's the meaning of the MkFFI C_Types String String signature?
*lecture2> :t x
x : IO' (MkFFI C_Types String String) Int
I then attempted to evaluate x from the REPL:
*lecture2> :exec x
main:When checking argument value to function Prelude.Basics.the:
Type mismatch between
IO Int (Type of x)
and
Integer (Expected type)
Also, why doesn't 42 print out in the REPL?
Looking at its type, what's the meaning of the MkFFI C_Types String String signature?
The IO' type constructor is parametrised over the FFI that is available within it. It'll be different depending on e.g. the backend you want to target. Here you have access to the C FFI which is the default one IO picks.
You can find out about these things by using :doc in the REPL. E.g. :doc IO' yields:
Data type IO' : (lang : FFI) -> Type -> Type
The IO type, parameterised over the FFI that is available within it.
Constructors:
MkIO : (World -> PrimIO (WorldRes a)) -> IO' lang a
Also, why doesn't 42 print out in the REPL?
I don't know how :exec x is supposed to work but you can evaluate x in an interpreter by using :x x instead and that does yield a sensible output:
Idris> :x x
MkIO (\w => prim_io_pure 42) : IO' (MkFFI C_Types String String) Int