All Projects → tpoulsen → Focus

tpoulsen / Focus

Licence: bsd-2-clause
Lightweight Elixir lenses

Programming Languages

elixir
2628 projects

Labels

Projects that are alternatives of or similar to Focus

Dontfeartheprofunctoroptics
Don't Fear the Profunctor Optics!
Stars: ✭ 367 (+63.84%)
Mutual labels:  lenses
Dart functional data
Simple and non-intrusive code generator for lenses and boilerplate of data types
Stars: ✭ 39 (-82.59%)
Mutual labels:  lenses
Typed
The TypeScript Standard Library
Stars: ✭ 124 (-44.64%)
Mutual labels:  lenses
Fsharpplus
Extensions for F#
Stars: ✭ 589 (+162.95%)
Mutual labels:  lenses
Frunk
Funktional generic type-level programming in Rust: HList, Coproduct, Generic, LabelledGeneric, Validated, Monoid and friends.
Stars: ✭ 725 (+223.66%)
Mutual labels:  lenses
Prolens
👓 Profunctor based lightweight implementation of Lenses
Stars: ✭ 63 (-71.87%)
Mutual labels:  lenses
Use Profunctor State
React Hook for state management with profunctor lenses
Stars: ✭ 331 (+47.77%)
Mutual labels:  lenses
Documentation
How does it all fit together?
Stars: ✭ 177 (-20.98%)
Mutual labels:  lenses
Lambda
Functional patterns for Java
Stars: ✭ 737 (+229.02%)
Mutual labels:  lenses
Lens Regex Pcre
Text lenses using PCRE regexes
Stars: ✭ 116 (-48.21%)
Mutual labels:  lenses
Focal
Program user interfaces the FRP way.
Stars: ✭ 613 (+173.66%)
Mutual labels:  lenses
Monocle Ts
Functional optics: a (partial) porting of Scala monocle
Stars: ✭ 657 (+193.3%)
Mutual labels:  lenses
To.ml
OCaml library for TOML
Stars: ✭ 68 (-69.64%)
Mutual labels:  lenses
Generic Lens
Generically derive traversals, lenses, and prisms.
Stars: ✭ 399 (+78.13%)
Mutual labels:  lenses
Elm Monocle
Functional abstractions to manipulate complex records in Elm - Iso, Prism, Lens, Optional, Traversal.
Stars: ✭ 137 (-38.84%)
Mutual labels:  lenses
Language Ext
C# functional language extensions - a base class library for functional programming
Stars: ✭ 3,964 (+1669.64%)
Mutual labels:  lenses
Lens
A Racket package for creating and composing pure functional lenses
Stars: ✭ 54 (-75.89%)
Mutual labels:  lenses
Python Lenses
A python lens library for manipulating deeply nested immutable structures
Stars: ✭ 179 (-20.09%)
Mutual labels:  lenses
Sauron
Yet another Scala lens macro
Stars: ✭ 166 (-25.89%)
Mutual labels:  lenses
Datum
pure functional and generic programming for Erlang
Stars: ✭ 111 (-50.45%)
Mutual labels:  lenses
  • Focus [[https://circleci.com/gh/tpoulsen/focus][https://circleci.com/gh/tpoulsen/focus.svg?style=svg]] [[https://img.shields.io/hexpm/v/focus.svg]]

#+ATTR_HTML: :style margin-left: auto; margin-right: auto; [[img/focus_lens_prism.png]]

Lightweight, pure Elixir functional optics[fn:1].

#+BEGIN_QUOTE A lens is a value that composes a getter and a setter function to produce a bidirectional view into a data structure. This definition is intentionally broad—lenses are a very general concept, and they can be applied to almost any kind of value that encapsulates data. -- [[https://docs.racket-lang.org/lens/lens-intro.html][Racket 'lens' documentation]] #+END_QUOTE

** Usage

To construct a lens:

#+BEGIN_SRC elixir

A lens for the key :name

Lens.make_lens(:name)

A lens for the key "name"

Lens.make_lens("name")

A lens for the second item in a tuple:

Lens.make_lens(1) #+END_SRC

Each lens provides both a getter and a setter for the accessor it was created for.

Lenses can be used to access and/or modify structured data:

#+BEGIN_SRC elixir

Extract a value from a simple map:

person = %{name: "Homer"} nameLens = Lens.make_lens(:name)

Focus.view(nameLens, person)

"Homer"

Focus.set(nameLens, person, "Bart")

%{name: "Bart"}

Focus.over(nameLens, person, &String.upcase/1)

%{name: "HOMER"}

#+END_SRC

Their real utility comes in operating on nested data. Lenses can be created by composing other lenses in order to traverse a data structure:

#+BEGIN_SRC elixir person = %{ name: "Homer", address: %{ locale: %{ number: 742, street: "Evergreen Terrace", city: "Springfield", }, state: "???" } }

To access the street, we can compose the lenses that lead there from the top level.

Lenses can be composed with Focus.compose/2, or the infix (~>) operator.

address = Lens.make_lens(:address) locale = Lens.make_lens(:locale) street = Lens.make_lens(:street)

address ~> locale ~> street |> Focus.view(person)

"Evergreen Terrace"

address ~> locale ~> street |> Focus.set(person, "Fake Street")

person = %{

name: "Homer",

address: %{

locale: %{

number: 742,

street: "Fake Street",

city: "Springfield",

},

state: "???"

}

}

#+END_SRC

** Macros *** Optic creation

  • =deflenses= :: A wrapper around =defstruct= that additionally defines lenses for the struct's keys inside the module. #+BEGIN_SRC elixir defmodule User do import Lens deflenses name: nil, age: nil

      # deflenses defines %User{}, User.name_lens/0, and User.age_lens/0
    end
    

    #+END_SRC

** Functions *** Optic creation

  • =Lens.make_lens/1=
  • =Lens.make_lenses/1=
  • =Lens.idx/1= *** Pre-made optics
  • =Prism.ok/0=
  • =Prism.error/0=

*** Optic application

  • =Focus.view/2=
  • =Focus.over/3=
  • =Focus.set/3=
  • =Focus.view_list/2=
  • =Focus.has/2=
  • =Focus.hasnt/2=
  • =Focus.fix_view/2=
  • =Focus.fix_over/3=
  • =Focus.fix_set/3=

*** Optic composition

  • =Focus.compose/2, (~>)=
  • =Focus.alongside/2=

** Installation

  1. Add =focus= to your list of dependencies in =mix.exs=:
#+BEGIN_SRC elixir
  def deps do
    [{:focus, "~> 0.3.5"}]
  end
#+END_SRC

** References

  • [[https://www.schoolofhaskell.com/user/tel/a-little-lens-starter-tutorial][A Little Lens Starter Tutorial]]
  • [[https://github.com/ekmett/lens/wiki/FAQ#lens-resources][ekmett/lens package FAQ]]
  • [[https://hackage.haskell.org/package/lens-tutorial-1.0.2/docs/Control-Lens-Tutorial.html][Control.Lens Tutorial]]
  • Footnotes

[fn:1] This library currently combines Lenses and Prisms with Traversals in its implementation. Until v1.0.0, the API is subject to large and frequent change.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].