Idiomatic way of using Functor/Applicative/Monad constructs in ST in Idris - monads

I tried using when : Applicative f => Bool -> Lazy (f ()) -> f () inside a ST do block:
loop : (ConsoleIO m, Draw m) =>
(draw : Var) ->
(state : GameState) ->
ST m () [draw ::: SDraw {m}]
loop draw state = with ST do
print (f state) -- works
when True (print (f state)) -- error
?what
which is an error because ST is not an applicative apparently, it merely supports do syntax.
I assume that there are other useful functor/applicative/monad functions that are also not supported because of this.
Is there some idiomatic solution for this lack?

Related

Circular dependencies between functions in Ocaml

I have seen some questions about circular dependencies in ocaml, but they were all about dependencies between types.
In my case, I have a function called eval. It simulates an interpreter for a made-up language and needs to call functions like this:
let rec eval e r =
match e with
(* ... *)
Forall(p, s) ->
let pred = eval p r in
let set = eval s r in
forall pred s |
(* ... *)
Problem is, forall looks something like this:
let forAll (p : exp) (s : evT) : evT =
match s with
SetVal(Empty(_)) -> (Bool true) |
SetVal(Set(lst, _)) ->
match p with
(* irrelevant code *)
match l with
[] -> acc |
h::t -> aux t ((eval (FunCall(p, (evTToExp h))) env0)::acc)
in
(* irrelevant code *)
As you can see, it both needs to be called by and call eval.
If I put the definition of eval first in my .ml file, I get Unbound value forall, otherwise I get Unbound value eval.
How do I solve this kind of dependency? How do I let ocaml know that it will find the definition of the missing function, somewhere else in the file?
Mutual recursion is accomplished with the rec and and keywords:
let rec eval = ...
and forAll = ...

foldrImpl and proofs

I've been using the Vect datatype a lot in my code. Frequently, I find myself having to prove something involving library functions over Vects which use foldr. Since foldr is implemented on top of foldrImpl, if I try to inspect the proof context by putting a hole that is what shows up in the goal. My issue is that it doesn't seem like idris can evaluate the foldrImpl in the goal type (similar behavior to when a function is not known to be total by the totality checker), what makes me get stuck on the proofs.
Usually my solution to this problem is to define my own version of a library function that does the folding from scratch. But that is clearly inconvenient since: (i) I have to code the functions that already exist in the library; (ii) this make me not use fold in any definitions that I intend to later prove something about.
For a concrete example, consider that I want to prove the following
lemma_take_head : {x : a} ->
{xs : List a} ->
{ls : Vect len (List a)} ->
concat ((x :: xs) :: ls) = x :: (concat (xs :: ls))
lemma_take_head {ls = []} = Refl
lemma_take_head {ls = l :: ls} = ?h2
With my version of concat, this is as easy as just returning Refl. But with the library version, which folds, we get the following context for the case when the Vect is topmost a cons:
a : Type
l : List a
x : a
xs : List a
len : Nat
ls : Vect len (List a)
--------------------------------------
h2 : foldrImpl (\meth, meth => meth ++ meth) [] (\x1 => x :: xs ++ l ++ x1) ls = x :: foldrImpl (\meth, meth => meth ++ meth) [] (\x1 => xs ++ l ++ x1) ls
Is there a way to continue proofs once they get to a point like this, or is the only solution to re-implement the functions in a way that they don't use folds?

Idris - lazy evaluation issue

Consider this program:
module test
import Effects
import Effect.StdIO
(>>==) : Maybe a -> Lazy (a -> Maybe b) -> Maybe b
(>>==) Nothing (Delay map) = Nothing
(>>==) (Just x) (Delay map) = map x
nothing : String -> Eff (Maybe String) [STDIO]
nothing s = do
putStrLn s
pure Nothing
func : Maybe String -> String -> Maybe String
func Nothing _ = Nothing
func (Just s) t = Just (s ++ t)
test : Eff () [STDIO]
test = do
let m = !(nothing "a") >>== (func !(nothing "b"))
putStrLn "end"
main : IO ()
main = run test
since the right hand side of >>== is declared lazy and !(nothing "a") returns Nothing, I would expect that the right hand side of >>== would not be evaluated.
But actually it does get evaluated, and I can't understand why...
More broadly, I'm trying to concatenate Eff computations that return maybe and stop the execution when I get the first Nothing
Desugar the ! notation.
test = do
x <- nothing "a"
y <- nothing "b"
let m = x >>== (func y)
putStrLn "end"
Clearly "a", "b", and "end" will all be printed, but func may not be evaluated.
I think you'll need have to define >>== to act on (some) Eff values, rather than directly on Maybes.
HTH

Is there a way to code a chainl function in idris lightyear library?

I'm trying to formalise a regular expression based string search tool in Idris
(current status here). But I'm fighting with the problem of parsing regular expressions. I've tried to build a small parsing library but gave up on this in favor to use Lightyear, a parsing combinator library for Idris.
Since I'm used to Haskell, I've tried to use a similar strategy that I would do using Parsec. My main problem is how to handle left recursion on Lightyear parsers? I've tried several encodings but pretty much all parsers end up looping and causing segmentation faults in generated code.
I don't know Lightyear, but I had some success porting Parsec to Idris:
module Parser
data Parser : Type -> Type where
P : (String -> List (a, String)) -> Parser a
unP : Parser a -> String -> List (a, String)
unP (P f) = f
total stripPrefix : (Eq a) => List a -> List a -> Maybe (List a)
stripPrefix [] ys = Just ys
stripPrefix (x::xs) (y::ys) = if (x == y) then stripPrefix xs ys else Nothing
stripPrefix _ _ = Nothing
total token : String -> Parser ()
token tk = P $ \s => case stripPrefix (unpack tk) (unpack s) of
Just s' => [((), pack s')]
Nothing => []
total skip : Parser ()
skip = P $ \s => case unpack s of
[] => []
(_::s') => [((), pack s')]
instance Functor Parser where
map f p = P $ \s => map (\(x, s') => (f x, s')) (unP p s)
instance Applicative Parser where
pure x = P $ \s => [(x, s)]
(P pf) <*> (P px) = P $ \s => concat (map (\(f, s') => map (\(x, s'') => (f x, s'')) (px s')) (pf s))
instance Alternative Parser where
empty = P $ \s => []
(P p1) <|> (P p2) = P $ \s => case p1 s of
[] => p2 s
results => results
instance Monad Parser where
px >>= f = P $ \s => concat (map (\(x, s') => unP (f x) s') (unP px s))
total runParser : Parser a -> String -> Maybe a
runParser (P p) s = case p s of
[(x, "")] => Just x
_ => Nothing
This allows a straight copy-paste implementation of chainl:
chainl1 : Parser a -> Parser (a -> a -> a) -> Parser a
chainl1 p op = p >>= rest
where
rest x = do { f <- op; y <- p; rest $ f x y } <|> return x
chainl : Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainl p op x = chainl1 p op <|> return x
We can then take a straight transliteration of the expression parser from the chainl docs (I'm too lazy to implement a proper integer parser so we'll just use unary):
parens : Parser a -> Parser a
parens p = token "(" *> p <* token ")"
symbol : String -> Parser ()
symbol = token
integer : Parser Nat
integer = P $ \s => case unpack s of
('Z'::s') => [(Z, pack s')]
('S'::s') => map (\(n, s'') => (S n, s'')) $ unP integer (pack s')
_ => []
mutual
expr : Parser Nat
expr = term `chainl1` addop
term : Parser Nat
term = factor `chainl1` mulop
factor : Parser Nat
factor = parens expr <|> integer
mulop : Parser (Nat -> Nat -> Nat)
mulop = (symbol "*" *> pure (*)) <|>
(symbol "/" *> pure div)
addop : Parser (Nat -> Nat -> Nat)
addop = (symbol "+" *> pure (+)) <|>
(symbol "-" *> pure (-))
Now, if you try this:
main : IO ()
main = do
s <- getLine
printLn $ runParser expr s
then it will have the same divergant behaviour that you've observed. However, we can make two small changes:
Introduce a lazy alternative combinator:
orElse : Parser a -> Lazy (Parser a) -> Parser a
orElse p1 p2 = P $ \s => case unP p1 s of
[] => unP p2 s
results => results
Make sure the recursive part of factor, i.e. the parens expr part, is in this lazy position, by flipping the two alternatives:
factor = integer `orElse` parens expr
This then works as expected:
13:06:07 [cactus#galaxy brainfuck]$ idris Expr.idr -o Expr
13:06:27 [cactus#galaxy brainfuck]$ echo "SZ+(SSZ*SSSZ)" | ./Expr
Just 7
The chainl and chainl1 combinators can be used with the Lightyear package. However, they are provided by default. I've added the combinators to my own modules where I've needed them:
chainl1 : Parser a -> Parser (a -> a -> a) -> Parser a
chainl1 p op = p >>= rest
where rest a1 = (do f <- op
a2 <- p
rest (f a1 a2)) <|> pure a1
chainl : Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainl p op a = (p `chainl1` op) <|> pure a
Seems to work fine. Hope that helps.

Ocaml List: Implement append and map functions

I'm currently trying to extend a friend's OCaml program. It's a huge collection of functions needed for some data analysis.. Since I'm not really an OCaml crack I'm currently stuck on a (for me) strange List implementation:
type 'a cell = Nil
| Cons of ('a * 'a llist)
and 'a llist = (unit -> 'a cell);;
I've figured out that this implements some sort of "lazy" list, but I have absolutely no idea how it really works. I need to implement an Append and a Map Function based on the above type. Has anybody got an idea how to do that?
Any help would really be appreciated!
let rec append l1 l2 =
match l1 () with
Nil -> l2 |
(Cons (a, l)) -> fun () -> (Cons (a, append l l2));;
let rec map f l =
fun () ->
match l () with
Nil -> Nil |
(Cons (a, r)) -> fun () -> (Cons (f a, map f r));;
The basic idea of this implementation of lazy lists is that each computation is encapsulated in a function (the technical term is a closure) via fun () -> x.
The expression x is then only evaluated when the function is applied to () (the unit value, which contains no information).
It might help to note that function closures are essentially equivalent to lazy values:
lazy n : 'a Lazy.t <=> (fun () -> n) : unit -> 'a
force x : 'a <=> x () : 'a
So the type 'a llist is equivalent to
type 'a llist = 'a cell Lazy.t
i.e., a lazy cell value.
A map implementation might make more sense in terms of the above definition
let rec map f lst =
match force lst with
| Nil -> lazy Nil
| Cons (hd,tl) -> lazy (Cons (f hd, map f tl))
Translating that back into closures:
let rec map f lst =
match lst () with
| Nil -> (fun () -> Nil)
| Cons (hd,tl) -> (fun () -> Cons (f hd, map f tl))
Similarly with append
let rec append a b =
match force a with
| Nil -> b
| Cons (hd,tl) -> lazy (Cons (hd, append tl b))
becomes
let rec append a b =
match a () with
| Nil -> b
| Cons (hd,tl) -> (fun () -> Cons (hd, append tl b))
I generally prefer to use the lazy syntax, since it makes it more clear what's going on.
Note, also, that a lazy suspension and a closure are not exactly equivalent. For example,
let x = lazy (print_endline "foo") in
force x;
force x
prints
foo
whereas
let x = fun () -> print_endline "foo" in
x ();
x ()
prints
foo
foo
The difference is that force computes the value of the expression exactly once.
Yes, the lists can be infinite. The code given in the other answers will append to the end of an infinite list, but there's no program you can write than can observe what is appended following an infinite list.