Translating "Putting Lenses to Work" into PureScript (Part 1)

John Wiegley recently presented Putting Lenses to Work and did a great job explaining lenses in Haskell. The use of lenses in PureScript is the same, albeit the syntax is slightly different. This post is the PureScript REPL session as I followed along (up till 23:51) and uses purescript-profunctor-lens.

A few introductory notes. The & operator is used in the video. This is for reverse application, and the PureScript equivelent is the # operator.

The following operators/functions can be found in these modules…

Function Module
(^?) (preview) Data.Lens.Fold
(ix) Data.Lens.Index
at Data.Lens.At
non Data.Lens.ISO
use Data.Lens.Getter
to Data.Lens.Getter
(^..) (toListOfOn) Data.Lens.Getter
(^?!) (unsafeView) Data.Lens.Getter

> newtype Recipe = Recipe { title :: String }
> instance showRecipe :: Show Recipe where show (Recipe {title}) = "Recipe: " <> title
> recipe = Recipe { title : "Brownies" }
> import Data.Lens
> _title = lens (\(Recipe {title}) -> title) (\(Recipe r) value -> Recipe (r {title = value}))

-- Getting Values - 2:42
> view _title recipe
Brownies

-- Setting Values - 3:31

> over _title (const "New Recipe") recipe
Recipe: New Recipe

> recipe # _title %~ (const "New Recipe")
Recipe: New Recipe

> (_title %~ (const "New Recipe")) recipe
Recipe: New Recipe

> _title %~ (const "New Recipe") $ recipe
Recipe: New Recipe


-- Prisms - 10:17

> import Data.Maybe
> view _Just (Nothing :: Maybe String)
""

> view _Just (Just "abc")
"abc"

> b = Just "hi."
> view _Just b
"hi."
> over _Just (flip append "goodbye") b
"hi.goodbye"

> over _Just (flip append "goodbye") b
Nothing

-- 16:05 Traversable

> import Data.Lens.Index
> [1,2,3] # ix 2 .~ 20
[1,2,20]

> [1,2,3] # ix 6 .~ 20
[1,2,3]

> b ^.. _Nothing
Nil

b ^.. _Just
> ("hi." : Nil)

--- 17:17

> import Data.Traversable
> import Data.Monoid.Additive
> [1,2,3,4] ^. (to (foldMap Additive))
(Additive 10)

---

> import Data.Tuple
> even a = mod a 2 == 0
> allOf _2 even (Tuple 1 1)
false

---

> allOf (traversed) even [2,2,1]
false

> allOf (traversed) even [2,2,2]
true

> allOf (traversed <<< _2) even [Tuple 2 1]
false

> allOf (traversed <<< _2) even [Tuple 2 2]
true

--- 21:08

> import Data.StrMap as StrMap
> import Data.Lens.At
> strmap = StrMap.fromFoldable [Tuple "user" "john", Tuple "id" "1"]
> strmap ^. (at "user")
Just "john"

> import Data.Map as Map
> mymap = Map.fromFoldable [Tuple 1 "john", Tuple 2 "terry"]
> mymap ^. (at 1)
Just "john"

> mymap ^. (at 5)
Nothing

--- 22:33

> mymap ^. at 5 <<< non "Not Found"
Just "Not Found"

-- 22:53

> mymap ^? ix 1
(Just "john")

> mymap ^? ix 7
Nothing

---

> import Partial.Unsafe
> import Data.Lens.Fold.Partial
> unsafePartial (mymap ^?! ix 1)
"john"

--- 23:24

> mymap # ix 1 .~ "5"
(fromFoldable [(Tuple 1 "5"),(Tuple 2 "terry")])

> mymap # ix 10 .~ "5"
(fromFoldable [(Tuple 1 "john"),(Tuple 2 "terry")])

--- 23:51

There doesn't appear to be a purescript-profunctor-lens equivelent of `failing`