Package

purescript-barlow-lens

Repository
sigma-andex/purescript-barlow-lens
License
MIT-0
Uploaded by
sigma-andex
Published on
2021-04-21

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

sky =
  { zodiac:
      { virgo:
          { alpha: "Spica"
          }
      }
  }

view (barlow (key :: _ "zodiac.virgo.alpha")) sky
-- "Spica"
over (barlow (key :: _ "zodiac.virgo.alpha")) toUpper sky
-- { zodiac: { virgo: { alpha: "SPICA" } } }
    
-- view (barlow (key :: _ "zodiac.virgo.alfa")) sky 
-- doesn't compile

Features

Barlow supports lens creation for the following types:

Deep sky 🌌

Maybe

Use ? to zoom into a Maybe.

sky =
  { zodiac:
      Just
        { virgo:
            Just
              { alpha: Just "Spica"
              }
        }
  }

preview (barlow (key :: _ "zodiac?.virgo?.alpha?")) sky

Either

Use < for Left and > for Right to zoom into an Either.

sky =
  { zodiac:
      Right
        { virgo:
            Just
              { alpha: Left "Spica"
              }
        }
  }

preview (barlow (key :: _ "zodiac>.virgo?.alpha<")) sky

Array and other Traversables

Use + to zoom into Traversables like Array.

sky =
  { zodiac:
      [ { virgo:
            Just
              { star: "Spica"
              }
        }
      , { virgo:
            Just
              { star: "Serpentis"
              }
        }
      ]
  }

over (barlow (key :: _ "zodiac+.virgo?.star")) toUpper sky

Newtype

Use ! to zoom into a Newtype.

newtype Alpha = Alpha { alpha :: String }
instance alphaNT :: Newtype Alpha { alpha :: String }

sky =
  { zodiac:
      Just
        { virgo:
            Alpha { alpha: "Spica"
            }
        }
  }

preview (barlow (key :: _ "zodiac?.virgo!.alpha")) sky

Data types (experimental)

Note: This feature is still experimental and might slightly change in the future 🛸.

Barlow now supports zooming into arbitrary sum and product data types as long as there is a Generic instance.

Use < and > to zoom into the left and right cases of your sum type.

data Zodiac
  = Carina String | Virgo String | CanisMaior String 

derive instance genericZodiac :: Generic Zodiac _

instance showZodiac :: Show Zodiac where
  show = genericShow

sky =
  { zodiac: CanisMaior "Sirius"
  }

-- Twice to the right for CanisMaior, once to the left for the String 
actual = preview (barlow (key :: _ "zodiac>><")) sky
-- Just "Sirius"

Use < and > to zoom into the left and right cases of your product type.

data Zodiac
  = Virgo { alpha :: String } { beta :: String } { gamma :: String } { delta :: String }

derive instance genericZodiac :: Generic Zodiac _

instance showZodiac :: Show Zodiac where
  show = genericShow

sky =
  { zodiac:
      { virgo:
          Virgo { alpha : "Spica"} { beta: "β Vir"} { gamma: "γ Vir B"} { delta: "δ Vir"}
      }
  }

actual = preview (barlow (key :: _ "zodiac.virgo>>>.delta")) sky
-- (Just "δ Vir")

And you can of course combine them. It is more readable if you separate your sum lens from your product lens with a . dot.

data Zodiac
  = Carina { alpha :: String } | Virgo { alpha :: String } { beta :: String } { gamma :: String } { delta :: String } | CanisMaior String 

derive instance genericZodiac :: Generic Zodiac _
derive instance eqZodiac :: Eq Zodiac

instance showZodiac :: Show Zodiac where
  show = genericShow

sky =
  { zodiac:
      { virgo:
          Virgo { alpha : "Spica"} { beta: "β Vir"} { gamma: "γ Vir B"} { delta: "δ Vir"}
      }
  }

over (barlow (key :: _ "zodiac.virgo><.>>>.delta")) toUpper sky
-- { zodiac: { virgo: Virgo9 { 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 further and reviewing my PRs.