Unifying record type - purescript

As a learning exercise, I'm trying to define a newtype to serve as a holder of functions that can convert Show-able values to Effects, i.e.:
newtype ShEff a = ShEff (forall eff. Show a => a -> Eff eff Unit)
However, this:
f :: forall a. ShEff a
f = ShEff logShow
fails to compile with this error:
Could not match type
( console :: CONSOLE
| t2
)
with type
eff1
while trying to match type Eff
( console :: CONSOLE
| t2
)
with type Eff eff1
while checking that expression logShow
has type t0 -> Eff eff1 Unit
in value declaration f
Can you point me in the right direction?

The type of logShow is
forall eff. Show a => a -> Eff (console :: CONSOLE | eff) Unit
so you can't store it inside ShEff, since that must work for every eff, and logShow only works for rows containing the CONSOLE effect.
You have two options:
Move the eff type argument outside ShEff:
newtype ShEff eff a = ShEff (a -> Eff eff Unit)
f :: forall a eff. Show a => ShEff (console :: CONSOLE | eff) a
f = ShEff logShow
Add the constraint inside ShEff:
newtype ShEff a = ShEff (forall eff. a -> Eff (console :: CONSOLE | eff) Unit)
f :: forall a eff. Show a => ShEff a
f = ShEff logShow
Also notice that I've moved the Show a constraint outside ShEff in both cases.

Related

How can I create a polymorphic "map xs f" function?

The statement of the problem.
Consider this definition of map:
Fixpoint map (xs: list nat): (nat -> nat) -> list nat := match xs with
| nil => fun _ => nil
| x::xs' => fun f => (f x) :: (map xs' f)
end.
It works like this:
Coq < Eval simpl in map (1::2::3::List.nil) (fun x => x + 1).
= 2 :: 3 :: 4 :: nil
: list nat
How can I extend it to work on any types?
For example, in Haskell I can simply write as follows:
map :: forall a b. [a] -> (a -> b) -> [b]
map xs = case xs of
[ ] -> \_ -> [ ]
(x:xs') -> \f -> f x: map xs' f
But in Coq, I do not understand where I could place this forall quantifier.
My efforts.
The syntax reference explains the syntax of Fixpoint thusly:
Fixpoint ident binders {struct ident}? : type? := term
— So evidently there is no place in the syntax for a quantifier that binds a type variable over both binders and type. I tried placing forall here and there by guesswork but I could not make it work.
I can see how the type section could be made polymorphic in the result type of the function parameter without touching the binders section:
Fixpoint map (xs: list nat): forall B, (nat -> B) -> list B := match xs with
| nil => fun _ => nil
| x::xs' => fun f => f x :: (map xs' f)
end.
— But unfortunately this also gives an error, and cryptic enough for me at that:
In environment
map : list nat -> forall B : Type, (nat -> B) -> list B
xs : list nat
T : Type
The term "nil" has type "list ?A" while it is expected to have type
"(nat -> T) -> list T".
So, even for this simpler case I have no solution.
So, what can be done?
In Coq, the Fixpoint command is just a wrapper around the fix term constructor, which allows us to define anonymous recursive functions. A direct definition of map could be given as follows:
Require Import Coq.Lists.List.
Import ListNotations.
Definition map_anon : forall A B, (A -> B) -> list A -> list B :=
fix map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
This is morally equivalent to the following definition:
Fixpoint map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
Notice that A and B are bound as regular variables: in Coq, there is no distinction between types and terms, and these declarations causes Coq to infer their types as being Type. No forall quantifier is needed for the definition.
You can list all your arguments, including type arguments, after the name of the function. You'll put any arguments that depend on other arguments after the argument they depend on.
Fixpoint map (A B: Type) (xs: list A) (f: A -> B): list B :=
[...]
If you prefer foralls, you simply need to move everything (except the recursive argument and any arguments it depends on) to after the :.
Fixpoint map (A B: Type) (xs: list A): forall (f: A -> B), list B :=
[...]
Two things to note here. Since nothing after f depends on f, you could use the -> notation. This is purely notation and doesn't have any semantic difference.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
[...]
The other thing to note is that when the arguments are after the : like this, we have to define a function, not just something in list B.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
fun f => [...]
This is why you got the error The term "nil" has type "list ?A" while it is expected to have type "(nat -> T) -> list T".. We needed a function, not just something of type list B, which is what nil is.

Haskell Couldn't match expected type ‘Item Nat’ with actual type ‘()’

I am given this source code.
data Nat = Zero | Succ Nat deriving Show
class FromList a where
type Item a :: *
fromList :: [Item a] -> a
and I should write the function fromList so it converts like this, for example:
fromList [(),(),()] :: Nat
===> Succ (Succ (Succ Zero))
My code is
instance FromList Nat where
fromList [] = Zero
fromList (a:as) = Succ (fromList as :: Nat)
If I use fromList [] :: Nat then the Answer is just Zero so it's right
but when I use fromList [(),(),()] :: Nat, I get an error:
Couldn't match expected type ‘Item Nat’ with actual type ‘()’
• In the expression: ()
In the first argument of ‘fromList’, namely ‘[(), (), ()]’
In the expression: fromList [(), (), ()] :: Nat
What am I doing wrong?
You need to define Item t for each instance of a type t that you implement. In other words, this can be solved with the addition of one line
instance FromList Nat where
type Item Nat = ()
fromList [] = Zero
fromList (a:as) = Succ (fromList as :: Nat)
Now Item Nat and () are unifiable and no error will occur.

Purescript Effects: Prevent deep nesting

Right now, main has the following signature:
main :: Eff (dom :: DOM) (Maybe (Eff (dom :: DOM) (Maybe Element)))
I'd like to have the following:
main :: Eff (dom :: DOM) (Maybe Element)
findItem :: forall e. IsElement e => e -> Eff (dom :: DOM) (Maybe Element)
findItem e = getElementsByClassName "thing" (toElement e) >>= (item 0)
-- main :: Eff (dom :: DOM) (Maybe Element)
main = (map findItem) <$> (window >>= document >>= body)
What is the best way to do this?
Of course, I could do the following:
findItem :: forall e. IsElement e => Maybe e -> Eff (dom :: DOM) (Maybe Element)
findItem (Just e) = getElementsByClassName "findItemEdit" (toElement e) >>= (item 0)
findItem Nothing = pure Nothing
main :: Eff (dom :: DOM) (Maybe Element)
main = findItem =<< body =<< document =<< window
But I'd like to not have the Maybe handling in the findItem function.
Use traverse :: forall a b eff. (a -> Eff eff b) -> Maybe a -> Eff eff (Maybe b). The function is more general, but that's how you'll want to use it. Whenever you find yourself wanting to "swap" two types, like Maybe a -> Eff eff (Maybe a), or Maybe (List a) -> List (Maybe a), you can use traverse or sequence.
Specifically, your main would look like:
main :: Eff (dom :: DOM) (Maybe Element)
main = do
mdocBody <- window >>= document >>= body
mmitem <- traverse findItem mdocBody
-- mmitem has type `Maybe (Maybe Element)`
-- we can use `join` to collapse
pure (join mmitem)
Or, as point free,
main :: Eff (dom :: DOM) (Maybe Element)
main =
window >>= document >>= body
>>= map join <<< traverse findItem
You could use the MaybeT monad transformer:
main = runMaybeT do
b <- MaybeT (window >>= document >>= body)
MaybeT (findItem b)
MaybeT is a newtype for a Maybe wrapped inside a monad m (in our case m is Eff (dom :: DOM)):
newtype MaybeT m a = MaybeT (m (Maybe a))
and its bind handles nesting and unnesting in just the way you'd like it to:
bind (MaybeT x) f = MaybeT do
x >>= case _ of
Nothing -> pure Nothing
Just y -> case f y of MaybeT m -> m
The best I can come up with is to use the Maybe catamorphism, which would essentially take the findItem from your first example and turn it into the findItem from your second example:
main :: Eff (dom :: DOM) (Maybe Element)
main = maybe (pure Nothing) findItem =<< body =<< document =<< window

(PureScript) How to create a Union of two separately defined rows of effects

I'm essentially needing to know how to write a function like this...
joinCommands :: forall e1 e2 e3
. Union e1 e2 e3
=> Eff e1 Unit
-> Eff e2 Unit
-> Eff e3 Unit
joinCommands fn1 fn2 = do
fn1
fn2
Which doesn't work. I get this error:
[PureScript] Could not match kind
Control.Monad.Eff.Effect
with kind
Type
More specifically, what I'm trying to do is combine two Arrays of user-supplied functionality. That is one part of the codebase (user supplied) returns Array (Eff e1 Unit) and another part (also user supplied) returns Array (Eff e2 Unit). And at the application's entrypoint (the "core" unaccessable to the user) those two sets need to combined so they can be run together. So really, I'm trying to write a function of type Array (Eff e1 Unit) -> Array (Eff e2 Unit) -> Array (Eff e3 Unit) where e3 unites all the effects of e1 and e2.
I figured it out. For the general case, I just needed to specific that each Eff has a type that is compatiable with each other (not necessarily the same).
joinCommands :: forall e. Eff e Unit -> Eff e Unit -> Eff e Unit
joinCommands fn1 fn2 = do
fn1
fn2
For the specific case, the answer is the same. The function signature would be forall e. Array (Eff e Unit) -> Array (Eff e Unit) -> Array (Eff e Unit) and the compiler can work out that the first set of Effs is compatible with the second set.
So if you had...
type Commands e = Array (Eff e Unit)
a :: forall e. Commands (random :: RANDOM | e)
a = []
b :: forall e. Commands (now :: NOW | e)
b = []
c :: forall e. Commands e -> Commands e -> Commands e
c = a <> b
... you can call c a b even though a and b both have different explicit effects.

All-quantified type variable in (value) constructor cannot be explicitly typed as wanted

I have the following GADT.
Inductive GADT : Type -> Type :=
| A : forall A, GADT A
| B : GADT bool.
And the following data type that has one constructor with an all-qualified type variable.
Inductive Wrap A :=
| wrap : GADT A -> Wrap A
| unwrap : forall X, GADT X -> (X -> Wrap A) -> Wrap A.
Then I want to define a recursive function that uses the function within unwrap.
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => match fx with
| A _ => None
| B => wrappedGADT (k true)
end
end.
With this definition I get the following error message.
The term "true" has type "bool" while it is expected to have type "T".
I was assuming that when I inspect fx and get case B, the parameter fx has type GADT bool, thus, the all-quantified type variable X is bool as well. Is this assumption wrong?
Next, I tried to explicitly type unwrap as follows.
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) : option (GADT A) :=
match xs with
| wrap _ x => Some x
| #nwrap _ bool fx k => match fx with
| A _ => None
| B => wrappedGADT (k true)
end
end.
With this definition I get a very weird error message.
The term "true" has type "Datatypes.bool" while it is expected to have type "bool".
Can anybody give any pointers to the origin of this problem?
Unfortunately, raw match statements in Coq aren't always very smart about the kind of reasoning you're applying here. The "convoy pattern" (see CPDT for more information about it) is usually the answer for resolving this type of problem. The immediate application here would look something like:
Fail Fixpoint wrappedGADT {A} (xs: Wrap A) {struct xs} : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => match fx in (GADT T)
return ((T -> Wrap A) -> option (GADT A)) with
| A _ => fun k0 => None
| B => fun k0 => wrappedGADT (k0 true)
end k
end.
However, this runs into another issue, that Coq isn't able to verify the termination condition after passing the function through the "convoy". It seems that to work around that, it suffices to first define the function of recursive calls on values of k and then convoy that instead:
Fixpoint wrappedGADT {A} (xs: Wrap A) {struct xs} : option (GADT A) :=
match xs with
| wrap _ x => Some x
| unwrap _ _ fx k => let r := fun x => wrappedGADT (k x) in
match fx in (GADT T)
return ((T -> option (GADT A)) -> option (GADT A)) with
| A _ => fun _ => None
| B => fun r' => r' true
end r
end.
For your second code attempt, you're creating a local variable bool to hold the type called X in the unwrap constructor, which is then shadowing the Datatypes.bool definition. In general, there's no way to match only on one specific type in the Coq kernel language (although typeclasses provide a way to simulate that, somewhat).
Here is an alternative implementation, which constructs wrappedGADT's body using tactics. It has one advantage that it doesn't require manual return annotations from the user. The overall structure closely resembles your original code with the match expression.
It is crucial to use induction xs as opposed to destruct xs here, because the Wrap type is recursive.
Fixpoint wrappedGADT' {A} (xs: Wrap A) : option (GADT A).
induction xs as [x | ? fx k r].
- exact (Some x).
- destruct fx as [T | ].
+ exact None.
+ exact (r true).
Defined.
Print wrappedGADT'.
Here is a proof that the two implementations are extensionally equal.
Goal forall (A : Type) (xs : Wrap A),
wrappedGADT xs = wrappedGADT' xs.
Proof with auto.
intros A xs.
induction xs...
destruct g...
simpl; rewrite H; destruct (w true)...
Qed.
If we look at the term generated for wrappedGADT' (using Print wrappedGADT'.), we'll be able to construct one more solution using the Wrap_rect induction principle generated for the Wrap datatype (I just removed unused variable k from the match expression in wrappedGADT'):
Definition wrappedGADT'' {A} (xs: Wrap A) : option (GADT A) :=
Wrap_rect _
_
(fun t => Some t)
(fun _ fx k r =>
match fx in (GADT T)
return ((T -> option (GADT A)) -> option (GADT A)) with
| A _ => fun _ => None
| B => fun r' => r' true
end r)
xs.
This solution can then lead to a solution a-la Daniel's, if we unfold Wrap_rect, implemented as Fixpoint itself.