Open jkarni opened 8 years ago
Why exclude '[]
?
@fizruk There's already a Monoid instance for Book '[]
I've been wondering if it is possible to merge two Book
s together, and the Monoid
instance seems to be what I could be looking for.
I managed to achieve a merging behaviour like so:
> import qualified Data.Type.Map as TMap
Prelude ComposeLTR Bookkeeper Bookkeeper.Internal TMap
> let (Book a) = (emptyBook & #foo =: 1 & #bar =: "bar"); (Book c) = (emptyBook & #baz =: 1) in TMap.union a c $> Book
Book {bar = "bar", baz = 1, foo = 1}
Currently the Monoid instance looks like so:
instance Monoid (Book' '[]) where
mempty = emptyBook
_ `mappend` _ = emptyBook
Would it make sense to extend it with the code above?
I also found it interesting to notice that TMap.union
doesn't seem to support overlaps. Could we have a merge that supports overwrites and/or recursive mappend
?
e.g.
((emptyBook & #baz =: "hello ") `overwriteBook` (emptyBook & #baz =: "world"))
== (emptyBook & #baz =: "world")
((emptyBook & #baz =: "hello ") <> (emptyBook & #baz =: "world"))
== (emptyBook & #baz =: "hello world")
I've tried to give this a go again just now:
appendOverwrite TMap.Empty x = x
appendOverwrite (TMap.Ext k v xs) ys = TMap.Ext k v (appendOverwrite xs (deleteTMapK k ys))
where
unBook (Book a) = a
deleteTMapK k m = unBook $ delete k (Book m)
Trying to mimic Data.Type.Map.append
:
append :: TMap.Map s -> TMap.Map t -> TMap.Map (s TSet.:++ t)
append TMap.Empty x = x
append (TMap.Ext k v xs) ys = TMap.Ext k v (append xs ys)
But I get the type error:
<interactive>:439:32: error:
• Couldn't match expected type ‘t’ with actual type ‘t1’
‘t’ is untouchable
inside the constraints: t2 ~ '[]
bound by a pattern with constructor: TMap.Empty :: TMap.Map '[],
in an equation for ‘appendOverwrite’
at <interactive>:439:17-26
‘t’ is a rigid type variable bound by
the inferred type of appendOverwrite :: TMap.Map t2 -> t1 -> t
at <interactive>:439:1
‘t1’ is a rigid type variable bound by
the inferred type of appendOverwrite :: TMap.Map t2 -> t1 -> t
at <interactive>:439:1
Possible fix: add a type signature for ‘appendOverwrite’
• In the expression: x
In an equation for ‘appendOverwrite’:
appendOverwrite TMap.Empty x = x
• Relevant bindings include
x :: t1 (bound at <interactive>:439:28)
appendOverwrite :: TMap.Map t2 -> t1 -> t
(bound at <interactive>:439:1)
<interactive>:440:86: error:
• Couldn't match expected type ‘Key field0’
with actual type ‘TMap.Var k’
• In the first argument of ‘deleteTMapK’, namely ‘k’
In the second argument of ‘appendOverwrite’, namely
‘(deleteTMapK k ys)’
In the third argument of ‘TMap.Ext’, namely
‘(appendOverwrite xs (deleteTMapK k ys))’
• Relevant bindings include
k :: TMap.Var k (bound at <interactive>:440:27)
I am not sure what is going awry. Maybe I don't have enough experience with -XTypeFamilies
(or something else) to decypher this at the moment.
So I thought to go for something a bit simpler, a sub-problem:
deleteAll TMap.Empty x = x
deleteAll (TMap.Ext k _ xs) ys = deleteAll xs (deleteTMapK k ys)
Which resulted in a rather similar type error:
<interactive>:447:26: error:
• Couldn't match expected type ‘t’ with actual type ‘t1’
‘t’ is untouchable
inside the constraints: t2 ~ '[]
bound by a pattern with constructor: TMap.Empty :: TMap.Map '[],
in an equation for ‘deleteAll’
at <interactive>:447:11-20
‘t’ is a rigid type variable bound by
the inferred type of deleteAll :: TMap.Map t2 -> t1 -> t
at <interactive>:447:1
‘t1’ is a rigid type variable bound by
the inferred type of deleteAll :: TMap.Map t2 -> t1 -> t
at <interactive>:447:1
Possible fix: add a type signature for ‘deleteAll’
• In the expression: x
In an equation for ‘deleteAll’: deleteAll TMap.Empty x = x
• Relevant bindings include
x :: t1 (bound at <interactive>:447:22)
deleteAll :: TMap.Map t2 -> t1 -> t (bound at <interactive>:447:1)
<interactive>:448:60: error:
• Couldn't match expected type ‘Key field0’
with actual type ‘TMap.Var k’
• In the first argument of ‘deleteTMapK’, namely ‘k’
In the second argument of ‘deleteAll’, namely ‘(deleteTMapK k ys)’
In the expression: deleteAll xs (deleteTMapK k ys)
• Relevant bindings include
k :: TMap.Var k (bound at <interactive>:448:21)
Any ideas on what may be going wrong above?
Or how we could have a working overwriteBook
function?
A bit of an update. Giving the following signature gets rid of the first type error:
appendOverwrite :: TMap.Map s -> TMap.Map t -> TMap.Map (s TSet.:++ t)
appendOverwrite TMap.Empty x = x
appendOverwrite (TMap.Ext k v xs) ys = TMap.Ext k v (appendOverwrite xs (deleteTMapK k ys))
Leaving us with: Couldn't match expected type ‘Key field0’ with actual type ‘TMap.Var k’
Which types are only nominally different, right? Could I convert between them somehow?
I've also tried to construct this without unBook . Book
but I haven't been successful yet.
For types other than
'[]