π
purescript-barlow-lens Barlow lens increases your magnification and let's you see the stars
In other words, barlow lens makes creating complex lenses such as record lenses super simple.
Installation
spago install barlow-lens
tl;dr
import Data.Lens
import Data.Lens.Barlow
import Data.String (toUpper)
sky = { zodiac: { virgo: { alpha: "Spica" } } }
spica = view (barlow (key :: _ "zodiac.virgo.alpha")) sky
-- "Spica"
upped = over (barlow (key :: _ "zodiac.virgo.alpha")) toUpper sky
-- { zodiac: { virgo: { alpha: "SPICA" } } }
-- alfa = view (barlow (key :: _ "zodiac.virgo.alfa")) sky
-- doesn't compile
or use the barlow helpers to make it even shorter:
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
import Data.String (toUpper)
sky = { zodiac: { virgo: { alpha: "Spica" } } }
spica = view (key :: _ "zodiac.virgo.alpha") sky
-- "Spica"
upped = over (key :: _ "zodiac.virgo.alpha") toUpper sky
-- { zodiac: { virgo: { alpha: "SPICA" } } }
Features
Barlow supports lens creation for the following types:
π₯ Records
π¦ π Maybe
- π€·π½ββοΈ
Either
π Array
(and otherTraversable
s)π Newtype
π€ Data types
π
Deep sky Maybe
Use ?
to zoom into a Maybe
.
import Data.Maybe (Maybe(..))
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
sky =
{ zodiac:
Just
{ virgo:
Just
{ alpha: Just "Spica"
}
}
}
spica = preview (key :: _ "zodiac?.virgo?.alpha?") sky
Either
Use <
for Left
and >
for Right
to zoom into an Either
.
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
import Data.String (toUpper)
sky =
{ zodiac:
Right
{ virgo:
Just
{ alpha: Left "Spica"
}
}
}
spica = preview (key :: _ "zodiac>.virgo?.alpha<") sky
Array and other Traversables
Use +
to zoom into Traversable
s like Array
.
import Data.Maybe (Maybe(..))
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
import Data.String (toUpper)
sky =
{ zodiac:
[ { virgo:
Just
{ star: "Spica"
}
}
, { virgo:
Just
{ star: "Serpentis"
}
}
]
}
upped = over (key :: _ "zodiac+.virgo?.star") toUpper sky
Newtype
Use !
to zoom into a Newtype
.
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
newtype Alpha = Alpha { alpha :: String }
instance Newtype Alpha { alpha :: String }
sky =
{ zodiac:
Just
{ virgo:
Alpha { alpha: "Spica"
}
}
}
spica = preview (key :: _ "zodiac?.virgo!.alpha") sky
Data types
Barlow supports zooming into arbitrary sum and product types as long as there is a Generic
instance.
Use %<NAME>
to zoom into sum types, where <NAME>
is the name of your data constructor. E.g. %Virgo
for the data constructor Virgo
.
Use %<INDEX>
to zoom into product types, where <INDEX>
is an integer between 1 and 9. Note that counting for product types and tuples usually starts with 1 and not 0. So the first element of a product is %1
.
It is more readable if you separate your sum lens from your product lens with a .
dot.
import Data.Lens.Barlow
import Data.Lens.Barlow.Helpers
import Data.Generic.Rep (class Generic)
import Data.Show.Generic (genericShow)
import Data.String.Common (toUpper)
data Zodiac
= Carina { alpha :: String }
| Virgo { alpha :: String } { beta :: String } { gamma :: String } { delta :: String }
| CanisMaior String
derive instance Generic Zodiac _
-- Optionally derive a show instance
instance Show Zodiac where
show = genericShow
sky =
{ zodiac:
Virgo { alpha : "Spica"} { beta: "Ξ² Vir"} { gamma: "Ξ³ Vir B"} { delta: "Ξ΄ Vir"}
}
upped = over (key :: _ "zodiac.%Virgo.%4.delta") toUpper sky
-- { zodiac: Virgo { alpha : "Spica"} { beta: "Ξ² Vir"} { gamma: "Ξ³ Vir B"} { delta: "Ξ VIR"} }
Credits
This lib was heavily inspired by this incredible blog post. Thanks also to @i-am-the-slime for pushing me to go further and for reviewing my PRs.