discrete-space-map (empty) → 0
raw patch · 5 files changed
+237/−0 lines, 5 filesdep +basedep +comonaddep +comonads-fdsetup-changed
Dependencies added: base, comonad, comonads-fd, keys, representable-functors, semigroupoids
Files
- Data/DiscreteSpaceMap.hs +97/−0
- Data/DiscreteSpaceMap/Internal.hs +86/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- discrete-space-map.cabal +22/−0
+ Data/DiscreteSpaceMap.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}+module Data.DiscreteSpaceMap (Pos(..), Map(..), modify) where++import Control.Comonad+import Control.Comonad.Store.Class+import Data.Key+import Data.Functor.Bind+import Data.Functor.Representable+import Data.Foldable+import Data.Traversable+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable++import Data.DiscreteSpaceMap.Internal++-- | `Map` is a zipper on an infinite perfect binary tree.+-- It contains the position and value of the focus.+-- The other values are stored in the derivative of a perfect binary tree.+--+-- Functions that combine 2 maps like `zipWith`, `zipWithKey` and `<@>` preserve the focus position of the second argument.+data Map p a = Map !p !a (MapD a) deriving Show++-- | Modify the value of the focus.+modify :: (a -> a) -> Map p a -> Map p a+modify m (Map p a f) = Map p (m a) f++type instance Key (Map p) = p++-- | @ `zipWith` :: Pos p => (a -> b -> c) -> Map p a -> Map p b -> Map p c@+instance Pos p => Zip (Map p) where+ zipWith f = zipWithKey (const f)+-- | @ `zipWithKey` :: Pos p => (p -> a -> b -> c) -> Map p a -> Map p b -> Map p c@+instance Pos p => ZipWithKey (Map p) where+ zipWithKey f as bs = Map p (f p a b) $ zipWithKeyD f p ca cb+ where+ Map p b cb = bs+ Map _ a ca = seek p as++-- | @ (`<@>`) :: Pos p => Map p (a -> b) -> Map p a -> Map p b@+instance Pos p => ComonadApply (Map p) where+ (<@>) = zap++-- | @+-- `extract` :: Map p a -> a+-- `extend` :: (Map p a -> b) -> Map p a -> Map p b@+instance Comonad (Map p) where+ extract (Map _ a _) = a+ extend f z@(Map p _ c) = Map p (f z) $ fmap (\a -> f (Map p a c)) c++-- | @+-- `pos` :: Pos p => Map p a -> p+-- `peek` :: Pos p => p -> Map p a -> a+-- `seek` :: Pos p => p -> Map p a -> Map p a+-- `seeks` :: Pos p => (p -> p) -> Map p a -> Map p a@+instance Pos p => ComonadStore p (Map p) where+ pos (Map p _ _) = p+ peek tp (Map sp a c) = fst $ gotoD sp tp (a, c)+ seek tp (Map sp a c) = let (a', c') = gotoD sp tp (a, c) in Map tp a' c'+ seeks f w = seek (f (pos w)) w++-- | @ `index` :: Pos p => Map p a -> p -> a@+instance Pos p => Indexable (Map p) where+ index = flip peek+instance Pos p => Lookup (Map p) where + lookup = lookupDefault+instance Pos p => Adjustable (Map p) where+ adjust f p z = seek (pos z) . modify f . seek p $ z+-- | @ `tabulate` :: Pos p => (p -> a) -> Map p a@+instance Pos p => Representable (Map p) where+ tabulate f = Map zero (f zero) (tabulateD f)++-- | @ `fmap` :: (a -> b) -> Map p a -> Map p b@+instance Functor (Map p) where+ fmap = fmapDefault +-- | @ `mapWithKey` :: Pos p => (p -> a -> b) -> Map p a -> Map p b@+instance Pos p => Keyed (Map p) where+ mapWithKey = mapWithKeyDefault+-- | @ `foldMap` :: Monoid m => (a -> m) -> Map p a -> m@+instance Foldable (Map p) where + foldMap = foldMapDefault+-- | @ `foldMapWithKey` :: (Pos p, Monoid m) => (p -> a -> m) -> Map p a -> m@+instance Pos p => FoldableWithKey (Map p) where+ foldMapWithKey = foldMapWithKeyDefault+instance Foldable1 (Map p) where + foldMap1 = foldMap1Default+instance Pos p => FoldableWithKey1 (Map p) where+ foldMapWithKey1 = foldMapWithKey1Default+-- | @ `traverse` :: Applicative f => (a -> f b) -> Map p a -> f (Map p b)@+instance Traversable (Map p) where+ traverse f = unwrapApplicative . traverse1 (WrapApplicative . f)+-- | @ `traverseWithKey` :: (Pos p, Applicative f) => (p -> a -> f b) -> Map p a -> f (Map p b)@+instance Pos p => TraversableWithKey (Map p) where+ traverseWithKey f = unwrapApplicative . traverseWithKey1 (\k a -> WrapApplicative (f k a))+instance Traversable1 (Map p) where+ traverse1 f (Map p a c) = Map p <$> f a <.> traverse1 f c+instance Pos p => TraversableWithKey1 (Map p) where+ traverseWithKey1 f (Map p a c) = Map p <$> f p a <.> traverseWithKey1D f p c
+ Data/DiscreteSpaceMap/Internal.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE FlexibleInstances #-}+module Data.DiscreteSpaceMap.Internal where++import Data.Functor.Bind+import Data.Foldable+import Data.Traversable+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable++-- | To be a key in the map, a position needs to be convertible to and from a stream of bits.+class Eq p => Pos p where+ uncons :: p -> (p, Bool)+ cons :: (p, Bool) -> p+ -- ^ > cons . uncons == id + zero :: p+ -- ^ > uncons zero == (zero, False)+++-- | 1D discrete space+instance Pos Integer where+ zero = 0+ uncons i = let (d, m) = i `divMod` 2 in (negate d, m == 1)+ cons (i, b) = (if b then 1 else 0) - 2 * i++-- | 2D discrete space+instance Pos p => Pos (p, p) where+ zero = (zero, zero)+ uncons (x, y) = let (x', b) = uncons x in ((y, x'), b)+ cons ((x, y), b) = (cons (y, b), x)++-- | 3D discrete space+instance Pos p => Pos (p, p, p) where+ zero = (zero, zero, zero)+ uncons (x, y, z) = let (x', b) = uncons x in ((y, z, x'), b)+ cons ((x, y, z), b) = (cons (z, b), x, y)++-- | @[Bool]@ is the free instance of `Pos`.+instance Pos [Bool] where+ zero = []+ uncons [] = ([], False)+ uncons (b:bs) = (bs, b)+ cons (bs, b) = b:bs+++data MapD a = MapD a (MapD (a, a)) deriving Show++instance Functor MapD where+ fmap = fmapDefault+instance Foldable MapD where+ foldMap = foldMapDefault+instance Foldable1 MapD where+ foldMap1 = foldMap1Default+instance Traversable MapD where+ traverse f = unwrapApplicative . traverse1 (WrapApplicative . f)+instance Traversable1 MapD where+ traverse1 f (MapD a ca) = MapD <$> f a <.> traverse1 (\(a1, a2) -> (,) <$> f a1 <.> f a2) ca++gotoD :: Pos p => p -> p -> (a, MapD a) -> (a, MapD a)+gotoD sp tp | sp == tp = id+ | otherwise = down tb . gotoD sp' tp' . up sb+ where+ (tp', tb) = uncons tp+ (sp', sb) = uncons sp+ up False (a, MapD b c) = ((a, b), c)+ up True (b, MapD a c) = ((a, b), c)+ down False ((a, b), c) = (a, MapD b c)+ down True ((a, b), c) = (b, MapD a c)++tabulateD :: Pos p => (p -> a) -> MapD a+tabulateD f = MapD (f (cons (zero, True))) $ tabulateD (\p -> (f (cons (p, False)), f (cons (p, True)))) ++zipWithKeyD :: Pos p => (p -> a -> b -> c) -> p -> MapD a -> MapD b -> MapD c+zipWithKeyD f p (MapD a ca) (MapD b cb) = + MapD (f pOther a b) (zipWithKeyD f' pUp ca cb)+ where + (pUp, s) = uncons p+ pOther = cons (pUp, not s)+ f' p' (a1, a2) (b1, b2) = (f (cons (p', False)) a1 b1, f (cons (p', True)) a2 b2)++traverseWithKey1D :: (Pos p, Apply f) => (p -> a -> f b) -> p -> MapD a -> f (MapD b)+traverseWithKey1D f p (MapD a ca) = + MapD <$> f pOther a <.> traverseWithKey1D f' pUp ca+ where + (pUp, s) = uncons p+ pOther = cons (pUp, not s)+ f' p' (a1, a2) = (,) <$> f (cons (p', False)) a1 <.> f (cons (p', True)) a2
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Sjoerd Visscher++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Sjoerd Visscher nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ discrete-space-map.cabal view
@@ -0,0 +1,22 @@+name: discrete-space-map+version: 0+synopsis: A discrete space map.+description: A discrete space map implemented as a zipper on an infinite perfect binary tree.+homepage: https://github.com/sjoerdvisscher/discrete-space-map+license: BSD3+license-file: LICENSE+author: Sjoerd Visscher+maintainer: sjoerd@w3future.com+category: Data+build-type: Simple+cabal-version: >=1.8++library+ exposed-modules: Data.DiscreteSpaceMap+ other-modules: Data.DiscreteSpaceMap.Internal+ build-depends: base ==4.6.*,+ comonad ==3.0.*,+ comonads-fd ==3.0.*,+ keys ==3.0.*,+ semigroupoids ==3.0.*, + representable-functors ==3.0.*