Skip to content

Instantly share code, notes, and snippets.

@sebastiaanvisser
Created April 1, 2014 08:06
Show Gist options
  • Save sebastiaanvisser/9909890 to your computer and use it in GitHub Desktop.
Save sebastiaanvisser/9909890 to your computer and use it in GitHub Desktop.
Paths, lenses combined with a name.
{-# LANGUAGE
Arrows
, FlexibleInstances
, MultiParamTypeClasses
, TypeOperators
#-}
module Path where
import Control.Arrow
import Control.Category
import Control.Monad.Writer
import Data.Text (Text, splitOn)
import Prelude hiding ((.), id)
import qualified Data.Text as Text
import qualified Data.Label.Abstract as Label
{-# INLINE get #-}
{-# INLINE set #-}
{-# INLINE modify #-}
parse :: Text -> [Text]
parse t =
case splitOn "/" t of
[] -> []
x:xs -> map Text.strip (x : filter (not . Text.null) xs)
-- | Paths are lenses that store an observable textual path from the outer
-- structure to the inner value that they reference.
data Path arr f a = Path
{ segments :: [Text]
, run :: Label.Lens arr f a
}
instance ArrowApply arr => Category (Path arr) where
id = Path [] id
Path n a . Path m b = Path (n <> m) (a . b)
{-# INLINE id #-}
{-# INLINE (.) #-}
lens :: Text -> (f `arr` a) -> ((a, f) `arr` f) -> Path arr f a
lens n g s = Path [n] (Label.lens g s)
get :: Arrow arr => Path arr f a -> f `arr` a
get = Label.get . run
set :: Arrow arr => Path arr f a -> (a, f) `arr` f
set = Label.set . run
modify :: ArrowApply arr => Path arr f o -> (o `arr` o, f) `arr` f
modify = Label.modify . run
instance Arrow arr => Label.Iso arr (Path arr f) where
iso bi = proc (Path n l) ->
do m <- Label.iso bi -< l;
id -< Path n m
{-# INLINE iso #-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment