Skip to content
This repository has been archived by the owner on Oct 18, 2018. It is now read-only.
/ focus Public archive
forked from evancz/focus

A library for getting and setting values in deeply nested data structures.

License

Notifications You must be signed in to change notification settings

karldray/focus

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Focus

A Focus is a way to work with particular parts of a large chunk of data. On the most basic level, it lets you get and set fields of a record in a simple and composable way. This means you could avoid writing special record update syntax and use something that composes much more elegantly.

It gives you the ability to write stuff like freeze in the following snippet:

mario =
    { super = False
    , fire  = False
    , physics = { position = { x=3, y=4 }
                , velocity = { x=1, y=1 }
                }
    }

freeze object =
    set (physics => velocity) { x=0, y=0 } object

The actual goal of this library is to help architect large projects with many independent widgets. If we have three widgets with some shared state, we do not necassarily want to give each widget full access to that shared state. Instead we can have them return a function that acts just on the state they care about, and we can use a Focus to apply that change.

It is not yet clear if this will actually be any nicer than just using typical record update syntax in a well-architected application, because it is likely no one is actually dealing with particularly deep records. More experimentation is needed to figure this out.

Possible Anti-Pattern?

It is possible that the concept of a Focus is harmful to code quality in that it can help you to be lax with abstraction boundaries. By making it easy to look deep inside of data structures, it encourages you to stop thinking about how to make these substructures modular, perhaps leading to an architecture that is not as nice and has extra conceptual complexity.

The deeper problem may be that lenses are best when they are bidirectional, whereas a Focus is only in one direction. The issue is then that making proper lenses is not necessarily possible without changing the language itself.

Background

This API is inspired by the concept of Bidirectional Lenses as described by Nate Foster and seen in a modified form in Haskell as "lenses" and in ClojureScript as "cursors". My personal opinions and understanding come primarily from this talk by Simon Peyton Jones and Nate Foster's PhD dissertation on bidirectional lenses. I chose the name "Focus" because it is sort of like a lens that only lets you see in one direction.

Making Focus more convenient

Implementations of this idea in JS and Clojure rely heavily on the fact that the languages are dynamically typed and you can do runtime introspection. Haskell relies heavily on Template Haskell (a sort of macro system) to generate all of the necessary code. In Elm, type-directed macros may make things more convenient, but it is unclear exactly how this might work or if it is worthwhile.

About

A library for getting and setting values in deeply nested data structures.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Elm 100.0%