I have thought about this problem a lot and the only 'good' solution
that comes to my mind is to really deeply embed lists and the 'PosInf'
data structure. Up to now I could not find any other places where
custom data structures cause conflicts for the deep embedding.
I have looked at where 'PosInf' is actually used to find out how much
work it would cause to generalize it.
'diagrams-lib' only uses 'PosInf' in the file
'Diagrams/TwoD/Segment.hs'. So the work here is decently small.
'diagrams-core' only uses 'PosInf' in the file
'Diagrams/Core/Trace.hs'. So the work here is also decently small.
The packages 'diagrams-contrib', 'diagrams-cairo', 'diagrams-canvas'
and 'diagrams-svg' don't use 'PosInf' at all.
So there isn't really much work to do to chang from PosInf to a deep
embedded version of it.
I would approach a deep embedding of 'PosInf' like this:
{-# LANGUAGE FlexibleContexts #-}
import Data.Monoid.PosInf
import Data.Boolean
import Data.Deep.Error
class PosInfD p where
finiteD :: a -> p a
posInfinityD :: p a
deconsPosInfD :: (a -> b) -> b -> p a -> b
instance PosInfD PosInf where
finiteD = Finite
posInfinityD = PosInfty
deconsPosInfD f _ (Finite x) = f x
deconsPosInfD _ e PosInfty = e
isFiniteD :: ( PosInfD posinf
, Boolean (BooleanOf (posinf a))
) => posinf a -> BooleanOf (posinf a)
isFiniteD = deconsPosInfD (const true) false
isPosInftyD :: ( PosInfD posinf
, Boolean (BooleanOf (posinf a))
) => posinf a -> BooleanOf (posinf a)
isPosInftyD = notB . isFiniteD
getFiniteD :: (ErrorD a, PosInfD posinf) => posinf a -> a
getFiniteD = deconsPosInfD id (errorD "getFiniteD: Not finite")
My approach to embedded lists can be found in [1]. I think the
implementation is straight forward. All important list functions can
be implemented based on the 'ListD' class. So the deep embedding
should be convenient to use for other developers. One thing to note is
the 'ErrorD' class which provides a custom way of throwing an error.
This is needed, because compilers like Sunroof will evaluate the
complete deep embedded code and a normal call to 'error' will raise an
exception during the compilation process. With the custom 'ErrorD'
class the error that might occur during the runtime of the deep
embedded code can occur there without interfering with the compilation
process.
I think I still need to add a type function like 'BooleanOf' for the
embedded lists and 'PosInf' ('ListOf' amd 'PosInfOf'), because
otherwise the ambiguity that 'BooleanOf' solves might also occur in
code using these structures. I will look into that a little bit more.
I will try my approach this Weekend some time.
[1]
https://github.com/jbracker/deep-embedded-data/blob/master/src/Data/Deep/List.hs
2013/1/8 Jan Bracker <
jan.b...@googlemail.com>: