purescript halogen - render elements or nothing conditionally - purescript

I have a utility function to conditinally render elements:
thanRender :: ∀ w i. Boolean -> EL.HTML w i -> EL.HTML w i
thanRender true h = h
thanRender _ _ = EL.text ""
Usage:
isJust state.foo `thanRender` (EL.h1_ [ EL.text state.title ])
Is there a better way to "render nothing" as to render EL.text "" ?

Related

how to code in coq a function that sum the integers represented by the 2 lists and boolean representing a holdback?

I want to set the recursive function badd_r: list bool -> list bool -> bool -> list bool that sum the integers represented by the 2 lists and boolean representing a holdback.
I need to use these two functions b1add_r(sum of two lists), bsucc(successor of a binary number represented by a list of booleans).
Here are the two functions:
Fixpoint bsucc (l: list bool): list bool :=
match l with
| [] =>[true]
| true::r => false:: (bsucc r)
| false::r => true::r
end.
Definition b1add_r b1 b2 r :=
match b1,b2 with
true, true => (r,true)
| true,false => (negb r, r)
| false, true => (negb r,r)
| false,false => (r, false)
end.
I have no idea how to code this function in coq and how to prove it...
Lemma badd_rOK: forall l1 l2 r,
value (badd_r l1 l2 r) = value l1 + value l2 + (if r then 1 else 0).
Fixpoint value (l: list bool) :=
match l with
| [] => 0
| true :: r => 1 + 2 * value r
| false :: r => 2 * value r
end.
Any help would be appreciated!
Your function may have the following form:
Fixpoint badd_r (l1 l2:list bool) (r : bool) : list bool :=
match l1, l2 with
nil, nil => (* base case 1 *)
| a::r1, nil => (* base case 2 *)
| nil, b::r2 => (* base case 3 *)
| a::r1, b:: r2 => let (c, r') := b1add_r a b r
in (* recursive case *)
end.
In order to fill the holes/comments, and plan to prove correctness, you may relate arithmetic properties with the possible cases.
For instance, the equality (1+2*x)+(0+2*y)+1= 0+2(x+y+1) corresponds to the case add_r (true::r) (false::s) true = false :: (add_r r s true)

Coq how to target and transform hypotheses to show that they're false?

I'm trying to prove that if two lists of booleans are equal (using a definition of equality that walks the lists structurally in the obvious way), then they have the same length.
In the course of doing so, however, I end up in a situation with a hypothesis that is false/uninhabited, but not literally False (and thus can't be targeted by the contradiction tactic).
Here's what I have so far.
Require Import Coq.Lists.List.
Require Export Coq.Bool.Bool.
Require Import Lists.List.
Import ListNotations.
Open Scope list_scope.
Open Scope nat_scope.
Fixpoint list_bool_eq (a : list bool) (b: list bool) : bool :=
match (a, b) with
| ([], []) => true
| ([], _) => false
| (_, []) => false
| (true::a', true::b') => list_bool_eq a' b'
| (false::a', false::b') => list_bool_eq a' b'
| _ => false
end.
Fixpoint length (a : list bool) : nat :=
match a with
| [] => O
| _::a' => S (length a')
end.
Theorem equal_implies_same_length : forall (a b : list bool) , (list_bool_eq a b) = true -> (length a) = (length b).
intros.
induction a.
induction b.
simpl. reflexivity.
After this, the "goal state" (what's the right word?) of coq as shown by coqide looks like this.
2 subgoals
a : bool
b : list bool
H : list_bool_eq [] (a :: b) = true
IHb : list_bool_eq [] b = true -> length [] = length b
______________________________________(1/2)
length [] = length (a :: b)
______________________________________(2/2)
length (a :: a0) = length b
Clearing away some of the extraneous detail...
Focus 1.
clear IHb.
We get
1 subgoal
a : bool
b : list bool
H : list_bool_eq [] (a :: b) = true
______________________________________(1/1)
length [] = length (a :: b)
To us, as humans, length [] = length (a :: b) is clearly false/uninhabited, but that's okay because H : list_bool_eq [] (a :: b) = true is false too.
However, the hypothesis H is not literally False, so we can't just use contradiction.
How do I target/"focus my attention from the perspective of Coq" on the hypothesis H so I can show that it's uninhabited. Is there something roughly analogous to a proof bullet -, +, *, { ... } that creates a new context inside my proof specifically for showing that a given hypothesis is false?
If you simplify your hypothesis (simpl in H), you will see that it is equivalent to false = true. At that point, you can conclude the goal with the easy tactic, which is capable of discharging such "obvious" contradictions even when they are syntactically equal to False. As a matter of fact, you should not even need to perform the simplification beforehand; easy should be powerful enough to figure out what is contradictory by itself.
(It would have been better to prove the following stronger result: forall l1 l2, list_bool_eq l1 l2 = true <-> l1 = l2.)

Is is possible to implement a Coq tactic that inspects a HintDb? If so, how?

For example, I would like a tactic that would iterate over all the resolve hints in a given HintDb and for each resolve hint h, it would do a pose h. . Is this possible? If so, how?
In Coq, there is not (unless you do fancy things with shelve and backtracking), but it is pretty straightforward in OCaml. For example, in the Fiat project, we have such tactics. For Coq 8.7:
In hint_db_extra_tactics.ml:
module WITH_DB =
struct
open Tacticals.New
open Names
open Ltac_plugin
(* [tac] : string representing identifier *)
(* [args] : tactic arguments *)
(* [ltac_lcall] : Build a tactic expression calling a variable let-bound to a tactic == [F] args *)
let ltac_lcall tac args =
Tacexpr.TacArg(Loc.tag ## Tacexpr.TacCall(Loc.tag ## (Misctypes.ArgVar(Loc.tag ## Names.Id.of_string tac),args)))
(* [ltac_letin] : Build a let tactic expression. let x := e1 in e2 *)
let ltac_letin (x, e1) e2 =
Tacexpr.TacLetIn(false,[(Loc.tag ## Names.Id.of_string x),e1],e2)
(* [ltac_apply] : Run a tactic with arguments... *)
let ltac_apply (f: Tacinterp.Value.t) (arg:Tacinterp.Value.t) =
let open Geninterp in
let ist = Tacinterp.default_ist () in
let id = Id.of_string "X" in
let idf = Id.of_string "F" in
let ist = { ist with Tacinterp.lfun = Id.Map.add idf f (Id.Map.add id arg ist.lfun) } in
let arg = Tacexpr.Reference (Misctypes.ArgVar (Loc.tag id)) in
Tacinterp.eval_tactic_ist ist
(ltac_lcall "F" [arg])
(* Lift a constructor to an ltac value. *)
let to_ltac_val c = Tacinterp.Value.of_constr c
let with_hint_db dbs tacK =
let open Proofview.Notations in
(* [dbs] : list of hint databases *)
(* [tacK] : tactic to run on a hint *)
Proofview.Goal.nf_enter begin
fun gl ->
let syms = ref [] in
let _ =
List.iter (fun l ->
(* Fetch the searchtable from the database*)
let db = Hints.searchtable_map l in
(* iterate over the hint database, pulling the hint *)
(* list out for each. *)
Hints.Hint_db.iter (fun _ _ hintlist ->
syms := hintlist::!syms) db) dbs in
(* Now iterate over the list of list of hints, *)
List.fold_left
(fun tac hints ->
List.fold_left
(fun tac (hint : Hints.full_hint) ->
let hint1 = hint.Hints.code in
Hints.run_hint hint1
(fun hint2 ->
(* match the type of the hint to pull out the lemma *)
match hint2 with
Hints.Give_exact ((lem, _, _) , _)
| Hints.Res_pf ((lem, _, _) , _)
| Hints.ERes_pf ((lem, _, _) , _) ->
let this_tac = ltac_apply tacK (Tacinterp.Value.of_constr lem) in
tclORELSE this_tac tac
| _ -> tac))
tac hints)
(tclFAIL 0 (Pp.str "No applicable tactic!")) !syms
end
let add_resolve_to_db lem db =
let open Proofview.Notations in
Proofview.Goal.nf_enter begin
fun gl ->
let _ = Hints.add_hints true db (Hints.HintsResolveEntry [({ Vernacexpr.hint_priority = Some 1 ; Vernacexpr.hint_pattern = None },false,true,Hints.PathAny,lem)]) in
tclIDTAC
end
end
In hint_db_extra_plugin.ml4:
open Hint_db_extra_tactics
open Stdarg
open Ltac_plugin
open Tacarg
DECLARE PLUGIN "hint_db_extra_plugin"
TACTIC EXTEND foreach_db
| [ "foreach" "[" ne_preident_list(l) "]" "run" tactic(k) ] ->
[ WITH_DB.with_hint_db l k ]
END
TACTIC EXTEND addto_db
| [ "add" constr(name) "to" ne_preident_list(l) ] ->
[ WITH_DB.add_resolve_to_db (Hints.IsConstr (name, Univ.ContextSet.empty)) l]
END;;
In hint_db_extra_plugin.mllib:
Hint_db_extra_tactics
Hint_db_extra_plugin
In HintDbExtra.v:
Declare ML Module "hint_db_extra_plugin".
Using this to solve the example posed in the problem statement, we can add:
In _CoqProject:
-R . Example
-I .
HintDbExtra.v
PoseDb.v
hint_db_extra_plugin.ml4
hint_db_extra_plugin.mllib
hint_db_extra_tactics.ml
In PoseDb.v:
Require Import HintDbExtra.
Ltac unique_pose v :=
lazymatch goal with
| [ H := v |- _ ] => fail
| _ => pose v
end.
Goal True.
repeat foreach [ core ] run unique_pose.
If you want to run a tactic on each hint in the hint database (rather than running a tactic on each hint in succession, until you find one that succeeds), you can change the tclORELSE in with_hint_db to some sort of sequencing operator (e.g., tclTHEN).

How to use guard in Eff monad

The example in Purescript by Example section 8.17 Mutable State:
https://leanpub.com/purescript/read#leanpub-auto-mutable-state
is a simulate function:
import Prelude
import Control.Monad.Eff (Eff, forE)
import Control.Monad.ST (ST, newSTRef, readSTRef, modifySTRef)
simulate :: forall eff h. Number -> Number -> Int -> Eff (st :: ST h | eff) Number
simulate x0 v0 time = do
ref <- newSTRef { x: x0, v: v0 }
forE 0 (time * 1000) \_ -> do
modifySTRef ref \o ->
{ v: o.v - 9.81 * 0.001
, x: o.x + o.v * 0.001
}
pure unit
final <- readSTRef ref
pure final.x
The function itself works fine. Say it needs to be modified to stop movement of the particle at some value of x. This:
import Prelude
import Control.MonadPlus (guard)
import Control.Monad.Eff (Eff, forE)
import Control.Monad.ST (ST, newSTRef, readSTRef, modifySTRef)
simulate :: forall eff h. Number -> Number -> Int -> Eff (st :: ST h | eff) Number
simulate x0 v0 time = do
ref <- newSTRef { x: x0, v: v0 }
forE 0 (time * 1000) \_ -> do
o <- readSTRef ref
let v = o.v - 9.81 * 0.001
let x = o.x + o.v * 0.001
guard (x < 100.0)
modifySTRef ref \o ->
{ v: v
, x: x
}
pure unit
final <- readSTRef ref
pure final.x
results in the following error:
No type class instance was found for
Control.MonadZero.MonadZero (Eff
( "st" :: ST h3
| eff4
)
)
...
Does this mean guard cannot be used in Eff monad at all? How would one write the code with the same intention in idiomatic purescript?
You can't use guard, but you can use when, which works with any Monad:
when (x < 100.0) $
modifySTRef ref \o ->
{ v: v
, x: x
}

How to access a list in OCaml

I want to write a function that could check every item in a list is true or false. If at least one element is false, it will return true, so that:
assert_eq "checkFalse [true; false; true]" (checkFalse [true; true; true]) false;
assert_eq "checkFalse [false; false]" (checkFalse [false; true]) true;
I am an absolute beginner in OCaml and I don't know how to approach this. I tried using a for loop, something like:
let rec checkFalse (bools: bool list) : bool =
for i = 0 to bools.length do
if bools.length == false then false
else... (I don't know how to continue)
Then it said "Unbound record field...."
I also tried using find like:
if (find false bools != Not_found) then true else false
But my ways did not work. I came from a Java background.
Take a look at the List module: http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html specifically the exists method. For what you want, you can simply do this:
List.exists (fun x -> not x) [true;true;...;false;...]
The exists function will return true if any element in the list satisfies the predicate (the function). In this case, the predicate is fun x -> not x which will return true if x is false.
For general list access, you generally do this using pattern matching and recursion, or using the functions iter, map, fold_left, and fold_right (among others). Here's an implementation of exists using pattern matching:
let rec exists f l = match l with
| [] -> false (* the list is empty, return false *)
| h::t -> if (f h) then true (* the list has a head and a (possibly empty) tail. Check the return value of the predicate 'f' when applied to the head *)
else exists f t (* the predicate is false, recursively call the `exists` function on the tail *)
edit: as Chuck has posted, instead of fun x -> not x you can just simply use not.
Another possibility is to use the mem function:
List.mem false bools
let rec checkFalse xs =
match xs with [] -> false
| false :: _ -> true
| _ :: tl -> checkFalse tl;;
The simplest way would just be let checkFalse = List.exists not.
List.exists takes a function and a list as arguments, and tells if the function you passed returns true for any element in the list. not returns the negation of a bool.
let checkFalse = List.exists (fun elem -> elem = false) your_list in
doc:
val exists : ('a -> bool) -> 'a list -> bool
exists p [a1; ...; an] checks if at least one element of the list satisfies the predicate p.
That is, it returns (p a1) || (p a2) || ... || (p an).