Applicative asking for unexpected type - idris

I'm having difficulty implementing Applicative for my type. Here's Functor
data Connection : repr -> out -> Type where
MkConnection : (repr -> ty) -> (ty -> out) -> Connection repr out
Functor (Connection repr) where
map f (MkConnection get g) = MkConnection get $ f . g
If I write Applicative with a hole
Applicative (Connection repr) where
pure x = ?rhs
I can type check to get
"src/Foo.idr" 94L, 4210C written
0 a : Type
0 repr : repr
x : a
------------------------------
rhs : Connection repr a
A search gives no results. Indeed, if I add more detail
Applicative (Connection repr) where
pure x = MkConnection ?get ?g
I get
"src/Foo.idr" 94L, 4223C written
Error: While processing right hand side of pure. When unifying Connection repr a and Connection repr a.
Mismatch between: Type and repr (implicitly bound at .../src/Foo.idr:94:5--94:34).
.../src/Foo.idr:94:14--94:34
|
94 | pure x = MkConnection ?get ?g
|
I would have thought I can implement that with
pure x = MkConnection (\r => ()) (\_ => x)
but I'm getting
"src/Foo.idr" 94L, 4235C written
Error: While processing right hand side of pure. When unifying Connection repr a and Connection repr a.
Mismatch between: Type and repr (implicitly bound at .../src/Foo.idr:94:5--94:47).
.../src/Foo.idr:94:14--94:47
|
94 | pure x = MkConnection (\r => ()) (\_ => x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It seems to be interpreting \r => () as a Type -> something

Related

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

Why string type is not being accepted if it was expected?

I am trying to create and use a stack object (modified to have strings) from here:
let s = object
val mutable v = [""; ""]
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd
| [] -> None
method push hd =
v <- hd :: v
end ;;
let () =
s#push "first";
s#push "second";
s#push "third";
print_endline s#pop; (* error from this line *)
print_endline s#pop;
print_endline s#pop;
However, I am getting following error:
$ ocaml objects.ml
File "./objects.ml", line 19, characters 15-20:
Error: This expression has type string option
but an expression was expected of type string
I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?
I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?
Because the expression s#pop doesn't have type string. Its type is string option, i.e., it is either Some s or None, where s has type string.
Look at the pop method implementation, which returns Some s if there are more elements waiting in the stack, or None if the stack is empty,
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd (* returns `Some hd` *)
| [] -> None (* returns `None` *)
You can implement a helper function, that will print a value of type string option, e.g.,
let print_some s = match s with
| None -> print_endline "empty"
| Some s -> print_endline s
Here is how it is used
let () =
s#push "first";
s#push "second";
s#push "third";
print_some s#pop;
print_some s#pop;
print_some s#pop;
Here are some alternative implementations of the stack object, that use other ways to communicate to the caller that the stack is empty, e.g., a sentinel value from the stack element domain (provided by a user), an exception, or the result type, parametrized with a stringly typed error.
let stack_with_sentinel empty = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> empty
end
let stack_with_exception = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> raise Not_found
end
let stack_with_result = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
Ok hd
| [] -> Error "empty stack"
end
There are many other ways to define it, but using the option type is the most common.

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

Constraining a function argument in an interface

What is the syntax to constrain a function argument in an interface which takes a function? I tried:
interface Num a => Color (f : a -> Type) where
defs...
But it says the Name a is not bound in interface...
Your interface actually has two parameters: a and f. But f should be enough to pick an implementation:
interface Num a => Color (a : Type) (f : a -> Type) | f where
f here is called a determining parameter.
Here's a nonsensical full example:
import Data.Fin
interface Num a => Color (a : Type) (f : a -> Type) | f where
foo : (x : a) -> f (1 + x)
Color Nat Fin where
foo _ = FZ
x : Fin 6
x = foo {f = Fin} 5

GHC rejects ST monad code as unable to unify type variables?

I wrote the following function:
(.>=.) :: Num a => STRef s a -> a -> Bool
r .>=. x = runST $ do
v <- readSTRef r
return $ v >= x
but when I tried to compile I got the following error:
Could not deduce (s ~ s1)
from the context (Num a)
bound by the type signature for
.>=. :: Num a => STRef s a -> a -> Bool
at test.hs:(27,1)-(29,16)
`s' is a rigid type variable bound by
the type signature for .>=. :: Num a => STRef s a -> a -> Bool
at test.hs:27:1
`s1' is a rigid type variable bound by
a type expected by the context: ST s1 Bool at test.hs:27:12
Expected type: STRef s1 a
Actual type: STRef s a
In the first argument of `readSTRef', namely `r'
In a stmt of a 'do' expression: v <- readSTRef r
Can anyone help?
This is exactly as intended. An STRef is only valid in one run of runST. And you try to put an external STRef into a new run of runST. That is not valid. That would allow arbitrary side-effects in pure code.
So, what you try is impossible to achieve. By design!
You need to stay within the ST context:
(.>=.) :: Ord a => STRef s a -> a -> ST s Bool
r .>=. x = do
v <- readSTRef r
return $ v >= x
(And as hammar points out, to use >= you need the Ord typeclass, which Num doesn't provide.)