Closed pcarbonn closed 5 years ago
If I say
Right leftovers -> VF leftovers
I get the following error message:
* Couldn't match type `haskus-utils-types-1.1:Haskus.Utils.Types.List.Index
(1
GHC.TypeNats.+ (1
GHC.TypeNats.+ haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(VariantF
'[ConsF Int, NilF]
(EADT '[ConsF Int, NilF]))
'[]
'[ConsF
Int
(Fix
(VariantF
'[ConsF Int, NilF])),
NilF
(Fix
(VariantF
'[ConsF Int, NilF]))]))
'[ConsF Int (Fix (VariantF '[ConsF Int, NilF])),
NilF (Fix (VariantF '[ConsF Int, NilF]))]'
with `VariantF '[ConsF Int, NilF] (EADT '[ConsF Int, NilF])'
Expected type: VariantF
(haskus-utils-types-1.1:Haskus.Utils.Types.List.Filter
(OddF Int)
(haskus-utils-types-1.1:Haskus.Utils.Types.List.Filter
(EvenF Int) '[EvenF Int, OddF Int, ConsF Int, NilF]))
(EADT '[ConsF Int, NilF])
Actual type: haskus-utils-types-1.1:Haskus.Utils.Types.List.Index
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(VariantF
(haskus-utils-types-1.1:Haskus.Utils.Types.List.Filter
(OddF Int)
(haskus-utils-types-1.1:Haskus.Utils.Types.List.Filter
(EvenF Int) '[EvenF Int, OddF Int, ConsF Int, NilF]))
(EADT '[ConsF Int, NilF]))
(ApplyAll (EADT '[ConsF Int, NilF]) '[ConsF Int, NilF])
(ApplyAll (EADT '[ConsF Int, NilF]) '[ConsF Int, NilF]))
(ApplyAll (EADT '[ConsF Int, NilF]) '[ConsF Int, NilF])
* In the first argument of `cata', namely `alg2'
In the expression: cata alg2
In an equation for `cataAlg2': cataAlg2 = cata alg2
|
112 | cataAlg2 = cata alg2
| ^^^^
Not sure how to fix it...
Yes! You can lift a VariantF
into another with liftVariantF
:
alg2 x = case splitVariantF @'[EvenF Int, OddF Int] x of
Left v -> variantFToCont v >::>
( \(EvenF a l) -> Cons a l
, \(OddF a l) -> Cons a l
)
Right leftovers -> Fix (liftVariantF leftovers)
I've updated the doc: https://docs.haskus.org/eadt/constructor_removal.html#generic-input-fixed-matches
Sounds terrific ! This can be used for nanopass in an interpreter.
I get an error when the list of constructor has only one element:
alg2 x = case splitVariantF @'[EvenF Int] x of
Left v -> variantFToCont v >::>
( \(EvenF a l) -> Cons a l
)
Right leftovers -> Fix (liftVariantF leftovers)
Indeed, a tuple cannot have just one element:
* The lambda expression `\ (EvenF a l) -> Cons a l'
has one argument,
but its type `ContListToTuple
'[EvenF Int (Fix (VariantF bs))] (Fix (VariantF bs))'
has none
In the second argument of `(>::>)',
Maybe we need another operator when there is only one match ?
There are at least two solutions:
1) You can use Single a which is a 1-tuple:
variantFToConf v >::> Single (\(EvenF a l) -> ...)
2) You can use popVariantF instead of splitVariantF + variantFToCont
:
alg2 x = case popVariantF @(EvenF Int) x of
Right (EvenF a l) -> Cons a l
Left leftovers -> Fix (liftVariantF leftovers)
I would use the second one.
Sounds good ! Thanks.
Woops, When I try your second solution:
alg2 x = case popVariantF @(EvenF Int) x of
Right (EvenF a l) -> Cons a l
Left leftovers -> Fix (liftVariantF leftovers)
cataAlg2 :: EADT '[EvenF Int, OddF Int, ConsF Int, NilF]
-> EADT '[ OddF Int, ConsF Int, NilF]
cataAlg2 = cata alg2
I get the following error:
* Could not deduce: ApplyAll (EADT bs) as0 ~ ApplyAll (EADT bs) as
from the context: (KnownNat
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(ConsF Int (EADT bs))
(ApplyAll (EADT bs) bs)
(ApplyAll (EADT bs) bs)),
KnownNat
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(ConsF Int) bs bs),
KnownNat
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(EvenF Int (EADT bs))
(ApplyAll (EADT bs) xs)
(ApplyAll (EADT bs) xs)),
Haskus.Utils.Variant.PopVariant
(ConsF Int (EADT bs)) (ApplyAll (EADT bs) bs),
Haskus.Utils.Variant.PopVariant
(EvenF Int (EADT bs)) (ApplyAll (EADT bs) xs),
Haskus.Utils.Variant.LiftVariant
(ApplyAll (EADT bs) as) (ApplyAll (EADT bs) bs),
haskus-utils-types-1.1:Haskus.Utils.Types.List.Index
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(ConsF Int) bs bs)
bs
~ ConsF Int,
haskus-utils-types-1.1:Haskus.Utils.Types.List.Index
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(EvenF Int (EADT bs))
(ApplyAll (EADT bs) xs)
(ApplyAll (EADT bs) xs))
(ApplyAll (EADT bs) xs)
~ EvenF Int (EADT bs),
haskus-utils-types-1.1:Haskus.Utils.Types.List.Filter
(EvenF Int (EADT bs)) (ApplyAll (EADT bs) xs)
~ ApplyAll (EADT bs) as,
haskus-utils-types-1.1:Haskus.Utils.Types.List.IsMember'
(ApplyAll (EADT bs) xs)
(EvenF Int (EADT bs))
(ApplyAll (EADT bs) xs)
~ 'True,
haskus-utils-types-1.1:Haskus.Utils.Types.List.Index
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
(ConsF Int (EADT bs))
(ApplyAll (EADT bs) bs)
(ApplyAll (EADT bs) bs))
(ApplyAll (EADT bs) bs)
~ ConsF Int (EADT bs),
haskus-utils-types-1.1:Haskus.Utils.Types.List.IsSubset as bs
~ 'True)
bound by the inferred type for `alg2':
forall (bs :: [* -> *]) (xs :: [* -> *]) (as :: [* -> *]).
(KnownNat
(haskus-utils-types-1.1:Haskus.Utils.Types.List.IndexOf'
...
I tried with 2.0.3, and I still get the error.
Also, the signature of (both versions of) alg2 is very very long. If I don't write it, I get a warning when -Wall option is activated : Top-level binding with no type signature.
Would it be possible to simplify the signatures, so that I can still use -Wall ?
I have just released haskus-utils-variant 2.1.1 which should fix your issue with popVariantF
. It also exports more constraint synonyms so that you can write the types more easily:
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
import Haskus.Utils.EADT hiding (Cons,Nil)
import Haskus.Utils.EADT.TH
import Haskus.Utils.Types.List
data ConsF a e = ConsF a e deriving (Functor)
data EvenF a e = EvenF a e deriving (Functor)
data OddF a e = OddF a e deriving (Functor)
data NilF e = NilF deriving (Functor)
eadtPattern 'ConsF "Cons"
eadtPattern 'EvenF "Even"
eadtPattern 'OddF "Odd"
eadtPattern 'NilF "Nil"
alg2 ::
( ConsF Int :<: ys
, PopVariantF (EvenF Int) xs (EADT ys)
, LiftVariantF (Remove (EvenF Int) xs) ys (EADT ys)
) => VariantF xs (EADT ys) -> EADT ys
alg2 x = case popVariantF @(EvenF Int) x of
Right (EvenF a l) -> Cons a l
Left leftovers -> Fix (liftVariantF leftovers)
cataAlg2 :: EADT '[EvenF Int, OddF Int, ConsF Int, NilF]
-> EADT '[ OddF Int, ConsF Int, NilF]
cataAlg2 = cata alg2
(Also note that Filter has been renamed into Remove)
Top class ! I have now finalized H-Calc, including an introduction to EADT in the README.
I 'm still struggling finding the correct signature of the alg2 version where the cata recursion-scheme is not used, but that's a minor issue:
alg4 x = case popVariantF @(EvenF Int) $ unfix x of
Right (EvenF a l) -> Cons a (alg4 l)
Left over -> Fix (liftVariantF $ fmap alg4 over)
I don't see anything wrong with this type signature:
alg4 ::
( ConsF Int :<: ys
, PopVariantF (EvenF Int) xs (EADT ys)
, LiftVariantF (Remove (EvenF Int) xs) ys (EADT ys)
) => EADT xs -> EADT ys
alg4 x = case popVariantF @(EvenF Int) $ unfix x of
Right (EvenF a l) -> Cons a (alg4 l)
Left other -> Fix (liftVariantF $ fmap alg4 other)
and yet, I get this error message:
* Could not deduce: Haskus.Utils.Types.List.IsMember'
(ApplyAll (Fix (VariantF xs)) xs)
(EvenF Int (Fix (VariantF xs)))
(ApplyAll (Fix (VariantF xs)) xs)
~ 'True
arising from a use of `popVariantF'
Any clue ?
Compared to the catamorphism approach with alg2
, here it's a kind of top-down approach hence the functor variable for "PopVariantF" has to be "EADT xs" and not "EADT ys":
alg4 ::
( ConsF Int :<: ys
, PopVariantF (EvenF Int) xs (EADT xs) -- here
, LiftVariantF (Remove (EvenF Int) xs) ys (EADT ys)
, Functor (VariantF (Remove (EvenF Int) xs))
) => EADT xs -> EADT ys
alg4 x = case popVariantF @(EvenF Int) $ unfix x of
Right (EvenF a l) -> Cons a (alg4 l)
Left over -> Fix (liftVariantF $ fmap alg4 over)
I'm trying to simplify generic constructor removal like this:
Unfortunately, I can't find a way to leave leftovers unchanged: is there a way out ?