Giter VIP home page Giter VIP logo

lens's Introduction

Lens: Lenses, Folds, and Traversals

Hackage Build Status Hackage Deps

This package provides families of lenses, isomorphisms, folds, traversals, getters and setters.

If you are looking for where to get started, a crash course video on how lens was constructed and how to use the basics is available on youtube. It is best watched in high definition to see the slides, but the slides are also available if you want to use them to follow along.

The FAQ, which provides links to a large number of different resources for learning about lenses and an overview of the derivation of these types can be found on the Lens Wiki along with a brief overview and some examples.

Documentation is available through github (for HEAD) or hackage for the current and preceding releases.

Field Guide

Lens Hierarchy

Examples

(See wiki/Examples)

First, import Control.Lens.

ghci> import Control.Lens

Now, you can read from lenses

ghci> ("hello","world")^._2
"world"

and you can write to lenses.

ghci> set _2 42 ("hello","world")
("hello",42)

Composing lenses for reading (or writing) goes in the order an imperative programmer would expect, and just uses (.) from the Prelude.

ghci> ("hello",("world","!!!"))^._2._1
"world"
ghci> set (_2._1) 42 ("hello",("world","!!!"))
("hello",(42,"!!!"))

You can make a Getter out of a pure function with to.

ghci> "hello"^.to length
5

You can easily compose a Getter with a Lens just using (.). No explicit coercion is necessary.

ghci> ("hello",("world","!!!"))^._2._2.to length
3

As we saw above, you can write to lenses and these writes can change the type of the container. (.~) is an infix alias for set.

ghci> _1 .~ "hello" $ ((),"world")
("hello","world")

Conversely view, can be used as a prefix alias for (^.).

ghci> view _2 (10,20)
20

There are a large number of other lens variants provided by the library, in particular a Traversal generalizes traverse from Data.Traversable.

We'll come back to those later, but continuing with just lenses:

You can let the library automatically derive lenses for fields of your data type

data Foo a = Foo { _bar :: Int, _baz :: Int, _quux :: a }
makeLenses ''Foo

This will automatically generate the following lenses:

bar, baz :: Lens' (Foo a) Int
quux :: Lens (Foo a) (Foo b) a b

A Lens takes 4 parameters because it can change the types of the whole when you change the type of the part.

Often you won't need this flexibility, a Lens' takes 2 parameters, and can be used directly as a Lens.

You can also write to setters that target multiple parts of a structure, or their composition with other lenses or setters. The canonical example of a setter is 'mapped':

mapped :: Functor f => Setter (f a) (f b) a b

over is then analogous to fmap, but parameterized on the Setter.

ghci> fmap succ [1,2,3]
[2,3,4]
ghci> over mapped succ [1,2,3]
[2,3,4]

The benefit is that you can use any Lens as a Setter, and the composition of setters with other setters or lenses using (.) yields a Setter.

ghci> over (mapped._2) succ [(1,2),(3,4)]
[(1,3),(3,5)]

(%~) is an infix alias for 'over', and the precedence lets you avoid swimming in parentheses:

ghci> _1.mapped._2.mapped %~ succ $ ([(42, "hello")],"world")
([(42, "ifmmp")],"world")

There are a number of combinators that resemble the +=, *=, etc. operators from C/C++ for working with the monad transformers.

There are +~, *~, etc. analogues to those combinators that work functionally, returning the modified version of the structure.

ghci> both *~ 2 $ (1,2)
(2,4)

There are combinators for manipulating the current state in a state monad as well

fresh :: MonadState Int m => m Int
fresh = id <+= 1

Anything you know how to do with a Foldable container, you can do with a Fold

ghci> :m + Data.Char Data.Text.Lens
ghci> allOf (folded.text) isLower ["hello"^.packed, "goodbye"^.packed]
True

You can also use this for generic programming. Combinators are included that are based on Neil Mitchell's uniplate, but which have been generalized to work on or as lenses, folds, and traversals.

ghci> :m + Data.Data.Lens
ghci> anyOf biplate (=="world") ("hello",(),[(2::Int,"world")])
True

As alluded to above, anything you know how to do with a Traversable you can do with a Traversal.

ghci> mapMOf (traverse._2) (\xs -> length xs <$ putStrLn xs) [(42,"hello"),(56,"world")]
"hello"
"world"
[(42,5),(56,5)]

Moreover, many of the lenses supplied are actually isomorphisms, that means you can use them directly as a lens or getter:

ghci> let hello = "hello"^.packed
"hello"
ghci> :t hello
hello :: Text

but you can also flip them around and use them as a lens the other way with from!

ghci> hello^.from packed.to length
5

You can automatically derive isomorphisms for your own newtypes with makePrisms. e.g.

newtype Neither a b = Neither { _nor :: Either a b } deriving (Show)
makePrisms ''Neither

will automatically derive

_Neither :: Iso (Neither a b) (Neither c d) (Either a b) (Either c d)

such that

_Neither.from _Neither = id
from _Neither._Neither = id

Alternatively, you can use makeLenses to automatically derive isomorphisms for your own newtypes. e.g..

makeLenses ''Neither

will automatically derive

nor :: Iso (Either a b) (Either c d) (Neither a b) (Neither c d)

which behaves identically to _Neither above.

There is also a fully operational, but simple game of Pong in the examples/ folder.

There are also a couple of hundred examples distributed throughout the haddock documentation.

Contact Information

Contributions and bug reports are welcome!

Please feel free to contact me through GitHub or on the #haskell-lens or #haskell IRC channel on Libera Chat.

-Edward Kmett

lens's People

Contributors

andysonnenburg avatar aristidb avatar arkeet avatar basdirks avatar bennofs avatar cchalmers avatar dag avatar debug-ito avatar ehird avatar ekmett avatar glguy avatar haasn avatar hvr avatar icelandjack avatar ion1 avatar liyang avatar mgsloan avatar mikeplus64 avatar mxswd avatar peaker avatar phadej avatar pthariensflame avatar ryanglscott avatar shachaf avatar sol avatar supki avatar taneb avatar thoughtpolice avatar treeowl avatar yairchu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lens's Issues

doc fix for fromWithin

15:08] edwardk: @messages
[15:08] lambdabot: nandsaid 1h 41m 20s ago: in the docs for ‘fromWithin’ you have fromWithin l = fromMaybe . within l; surely you mean fromJust? [15:08] edwardk: @tell nand yes
[15:08] lambdabot: Consider it noted.

Can we come up with a model for embedding/projection pairs?

Embedding/projection pairs would be nice to have an analogue to:

data Embedding a b = Embedding (a -> b) (b -> Maybe a)

data Projection a b = Projection (a -> Maybe b) (b -> a)

with the ability to flip back and forth, and treat them like a a getter (or fold) and/or traversal/lens in the right situations?

"at" example doesn't work

Trying the example from the source comments:

$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :m + Control.Lens Data.Map.Lens Data.Map
Prelude Control.Lens Data.Map.Lens Data.Map> fromList [("hello",12)] ^. at "hello"

<interactive>:3:28:
    No instance for (At [Char] (Map [Char]))
      arising from a use of `at'
    Possible fix:
      add an instance declaration for (At [Char] (Map [Char]))
    In the second argument of `(^.)', namely `at "hello"'
    In the expression: fromList [("hello", 12)] ^. at "hello"
    In an equation for `it':
        it = fromList [("hello", 12)] ^. at "hello"
Prelude Control.Lens Data.Map.Lens Data.Map>
Leaving GHCi.
$ cabal list --installed --simple-output | grep lens
lens 2.6.1

BTW, what is the equivalent of "at" for accessing the n-th element of a list? I am sorely missing a "cheat sheet" that lists the common cases of using lenses, instead of hunting them across all the source files... In fact I was creating an HUnit test file that does nothing but list all these common cases, when I run into the above.

Add more cases to Magnify?

When it was limited to folds we had a few more instances. It would be nice to handle more cases gracefully.

Dodek reported a makeClassy example issue on 7.4.1

Using makeClassy on:

data Foo = Foo { _fooX, _fooY :: Int }

in GHC 7.4.1, reportedly yields:

Main.hs:14:1:
    Illegal type variable name: `'
    When splicing a TH declaration:
      class HasFoo t_0
    where foo :: 
          fooX :: forall . 
          fooX = foo GHC.Base.. go_1
                   where go_1 _f_2 (Main.Foo __fooX'_3
                                             __fooY_4) = (\__fooX_5 -> Main.Foo __fooX_5 __fooY_4) Data.Functor.<$> _f_2 __fooX'_3
          fooY :: forall . 
          fooY = foo GHC.Base.. go_6
                   where go_6 _f_7 (Main.Foo __fooX_8
                                             __fooY'_9) = (\__fooY_10 -> Main.Foo __fooX_8 __fooY_10) Data.Functor.<$> _f_7 __fooY'_9

TODO: Confirm this behavior and fix it. =)

Type operator constructors for Simple

I'm sure that this has been pondered before, but I'd like to open a discussion about it. Simple lenses / traversals / isos are pretty common, so what if they had nice type operators?

These seem good:

type a :-> b = Simple Lens a b
type a :*> b = Simple Traversal a b
type a :<-> b = Simple Iso a b
type a :..> b = Fold a b

I was considering (:%>) for Lens, but decided on (:->) for nicer appearance and consistency with fclabels.

Not sure if I'd need these:

type a :^> b = Simple Getter b
type a :<~ b = Simple Setter b

And these'd be a little silly (but would still save parens!):

type (:@->) a b i = SimpleIndexedLens i a b
-- etc

I dunno about you, but I like these smileys - each variety is just a different nose!

Problem with generalized Getting

When we re-generalized Getting we introduced a problem.

If you go to use (^.) on a traversal with constraints on each argument, like, say, dynamic then you now have to use an explicit type signature, because otherwise the b and d variables in Traversal a b c d are totally unconstrained.

We need to come up with a work around.

Contractions for lens types

This is pretty unimportant, but it seems like it'd be good to have a conventional contraction for traversal. The main purpose of these is to provide suffixes for function names.

If we arrange the core type names by length:

Iso
Lens
Fold
Action
Getter
Setter
Traversal
Projection
MonadicFold

Towards the end, they become very unwieldy suffixes. However, thankfully, contractions are pretty straightforward:

Traversal   --> Trav
Projection  --> Proj
MonadicFold --> MFold

However, "Trav" seems weird. "Walk" came to mind, but unless that becomes convention, I'll stick to "Trav". Thoughts?

Add (|>) = flip ($)

This will let us pipeline a lot of the makeLensesFor, etc. code more cleanly.

Replacer?

Setters are capable of replacing the target value(s) because they are capable of modifying the target value(s). Modification always allows replacement as a special case (via const and its ilk), but you cannot generate modification from solely replacement (if you have both replacement and retrieval, you can, but then you just end up with a Traversal).

This seems to hint at a supertype of Setter: Replacer (plus Indexed and/or Simple variants, of course). Essentially:

  • Getter a c is isomorphic to a -> c
  • Setter a b c d is isomorphic to (c -> d) -> a -> b
  • Replacer a b d is isomorphic to d -> a -> b

I've come up with a couple of encodings for Replacer that try to fit within the van Laarhoven model, and I'd like to generate some discussion of this. It's not critical to me, but it is an interesting hole in the current design space.

  • type Replacer a b d = forall f. (Settable f) => (forall c. c -> f d) -> a -> f b
  • type Replacer a b d = forall f. (Settable f) => (Void -> f d) -> a -> f b

Add `<<~`

We can't chain assignment with <~.

TH-generated lenses on sum types throw `error`

...as you're aware ;-) But I didn't see the issue of partial lenses addressed in the docs or tutorial, so I thought opening a ticket would be best, if only as a place to address the issue once.

I want to build additional abstractions on top of lenses, but I don't find the current behavior of lens w/r/t sum types to be acceptable. Here are my questions:

  1. Is there a way to support "partial lenses" with maybe a less general constraint, like Applicative or something (sorry, I'm still getting oriented to this lens flavor)
  2. If so are there any plans to do this here, and if not, why not?

I'm aware that the usual "lens laws" don't really permit lenses on types with multiple constructors, but that seems more of an argument for coming up with a better lens-like thing or better laws, rather than sort of ignoring the issue.

lens-2.6.1 doesn't build on ghc 7.2.1

src/Control/Lens/WithIndex.hs:316:1:
    The multi-parameter class `TraversableWithIndex' cannot have generic methods
    In the class declaration for `TraversableWithIndex'

$ instead of %?

I think it would make sense to use $ instead of % where the mnemonic is for applying a function, given that ($) is the function application operator, e.g. ($=) instead of (%=), ($) instead of (%), and so on (Control.Lens.Setter, Type, IndexedLens, and IndexedSetter seem to be affected). Is there a rationale for % besides it being an otherwise unused symbol?

If you agree I can prepare a patch.

(I'm guessing operators with more than one % like (%%=) and (%%) should also become ($$=) and ($$) in that case, rather than keeping one of the %s?)

Add elements and elementsOf? (or something similar)

It is possible to traverse an indexed container using a predicate on the index.

elements :: TraversableWithIndex i t => (i -> Bool) -> IndexedTraversal i (t a) (t b) a b
elementsOf :: (i -> Bool) -> InxexedTraversal i a b c d -> IndexedTraversal i a b c d

Add some kind of lens based zipper?

I've been considering adding a zipper module for some time. I hacked up @jberryman's zippo library to use lens.

Issues:

Where to put it?

If it lived in Control.Lens.Zipper it would be odd if it wasn't exported from Control.Lens, (since I do re-export Control.Lens.* for everything except Control.Lens.Internal, but if it was exported from Control.Lens it would take a lot of useful names that I've deliberately avoided touching because they are popular in end user code.

Monadic traversals of state?

Capturing the relevant discussion on monadic traversals from #36.

@orenbenkiki commented an hour ago
As for the monadic modification application - intuitively, one would expect
that the order would be (1) getting the original value (2) invoking the
modification function to do whatever changes it wants and (3) taking the
final result and setting the value to it. In fact, I am hard pressed to
think of any other possible order. I agree things might get muddier if the
operator/function modifies several lensed locations inside the container;
here one could argue either for "modify one location at a time", so the
modification function of the 2nd location would see the updated 1st
location, or a more transactional "modify everything at once", where all
the modification functions see the original values. I think the
one-at-a-time approach is more consistent with the way the state monad
works in general, so I'd go with that; I also suspect that this would be
the "natural" semantics that would fall out of any reasonable code, but I
of course I didn't delve into the relevant source files.

I'm not certain what would be the ideal notation for a monadic %= / %%=
modification function. Perhaps |%= and |%%= (mnemonic: pipe the state
through the modification)?

I could whip up some patch code for |%=, |%%=, withValue and withModified
if you'd like... I'll fork the GIT repository and do all this the proper
way (which I should have done from the start, sorry about that).

Thanks again,

Oren Ben-Kiki

@orenbenkiki commented an hour ago
I think I understand the concern but it seems to me this applies only to
operations which work on multiple locations - indexed ones, at that.

That is, I am hard pressed to think of a case where using the simple
single-location '%=' and '%%=' with a monadic modification function would
cause the issues you describe, even when applied to a list (e.g., "list .
element 2 |%= monadicChangeElement").

Perhaps I am missing something...?

Oren.

ekmett commented an hour ago
Consider _last, and someone coming along and appending to the list in the meantime.
Or even _head when someone comes in and inserts something in the meantime, so the thing you based your updated head on is now shifted downstream.

ekmett commented an hour ago
These issues manifest themselves in other languages too. Many languages like c++ have iterators, but inserting into the container while iterating may or may not be legal, and leads to all sorts of confusing semantics and places where elements may be missed in the traversal.

orenbenkiki commented 32 minutes ago
Ouch. You are right, doing "list . _last |%= functionThatAppendsToList" would have ill-defined semantics. It is a pity to give up this very useful ability because of this edge case... but if we'd rather be safe than sorry, this kills "|%=" and "|%%=". If we'd rather maximize usability, I'm not so sure (people could be warned off this edge case). I guess leaving it out for now would be safest, this can always be re-visited in the future if there is sufficient demand for it.

ekmett commented just now
Going to close out the issue and leave it as a record of the discussion.

Add (^%)

A tighter associativity version of % that can be interleaved with (^.).

Factored into a separate issue -- this was previously an offshoot of issue #17.

class At?

Now that we have unordered-containers is it worth it to revisit the decision not to have a class for At?

Allow indexing of a traversable and/or foldable by ordinal position.

-- allow them to index by ordinal position
indexed :: Traversable a b c d -> IndexedTraversable Int a b c d
indexed :: Foldable a b c d -> IndexedFoldable Int a b c d

This would let us 'reindex' another indexedtraversal by position in a result list as well, because every indexedtraversal is a traversal.

Feature request: Lenses generation without type signatures

In the following code snippet it would be convenient to generate lenses without explicit type signatures for the purpose of documentation:

data A = A { _a  Int, _b  Int }

makeLensesNoTypeSignatures ''A

So we can have nice haddocks:

-- | Lens 'a'
a  Lens A A Int Int

-- | Lens 'b'
b  Lens A A Int Int

droppingWhile doesn't satisfy its stated equivalence

While the documentation in Control.Lens.Fold states that

dropWhile p ≡ toListOf (droppingWhile p folded)

we see that

Prelude Control.Lens> toListOf (droppingWhile (<=3) folded) [1,6,1]
[6]
Prelude Control.Lens> dropWhile (<=3) [1,6,1]
[6,1]

Can we implement a faster version of alongside?

We switched to a final encoding of Bazaar because it made cloning dramatically faster. Would a final encoding of Context have a similar performance impact? e.g.

newtype Store c d a = Store { runStore :: forall f. Functor f => (c -> f d) -> f a }

This might also speed up a number of Control.Lens.Plated combinators.

Parameterized makeClassy

Here is a possible approach for implementing makeClassy for parameterized containers. It works without any type-specific logic, as long as all the types are functional dependencies of the container type. This is something I sorely need in my code...

Sample code:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

module Sample where

import Control.Lens hiding (Simple)

-- Unparameterized classy containers are easy (yey!)

data Trivial = Trivial { _trivialField :: Int }

makeClassy ''Trivial

trivialAdd :: HasTrivial container => Int -> container -> Int
trivialAdd int container = int + container ^. trivialField

data TrivialContainer = TrivialContainer { _trivialContainer :: Trivial }

makeLenses ''TrivialContainer

instance HasTrivial TrivialContainer where
  trivial = trivialContainer

trivialExample :: Int -> TrivialContainer -> Int
trivialExample = trivialAdd

-- Parameterized containers seem possible:

data Simple num = Simple { _simpleField :: num }

makeLensesFor [ ("_simpleField", "__simpleField") ] ''Simple

-- Functional dependency to be compatible with the general case below.
class HasSimple container num | container -> num where
  simple :: SimpleLens container (Simple num)

instance HasSimple (Simple num) num where
  simple = id

simpleField :: forall container num . HasSimple container num => SimpleLens container num
simpleField = simple . __simpleField

simpleAdd :: forall container num . (HasSimple container num, Num num) => num -> container -> num
simpleAdd num container = num + container ^. simpleField

data SimpleContainer = SimpleContainer { _simpleContainer :: Simple Int }

makeLenses ''SimpleContainer

instance HasSimple SimpleContainer Int where
  simple = simpleContainer

simpleExample :: Int -> SimpleContainer -> Int
simpleExample = simpleAdd

-- This even works for multiple types which become "phantom" for some fields,
-- as long as all types are functional dependencies of the container:

data Complex foo bar = Complex { _complexFoo :: foo, _complexBar :: bar }

makeLensesFor [ ("_complexFoo", "__complexFoo"), ("_complexBar", "__complexBar") ] ''Complex

-- The functional dependencies here are required for this approach to work.
class HasComplex container foo bar | container -> foo, container -> bar where
  complex :: SimpleLens container (Complex foo bar)

instance HasComplex (Complex foo bar) foo bar where
  complex = id

complexFoo :: forall container foo bar . HasComplex container foo bar => SimpleLens container foo
complexFoo = complex . __complexFoo

complexBar :: forall container foo bar . HasComplex container foo bar => SimpleLens container bar
complexBar = complex . __complexBar

complexAddFoo :: forall container foo bar . (HasComplex container foo bar, Num foo) => foo -> container -> foo
complexAddFoo foo container =
  foo + container ^. complexFoo

complexAddBar :: forall container foo bar . (HasComplex container foo bar, Num bar) => bar -> container -> bar
complexAddBar bar container =
  bar + container ^. complexBar

data ComplexContainer = ComplexContainer { _complexContainer :: Complex Int Int }

makeLenses ''ComplexContainer

instance HasComplex ComplexContainer Int Int where
  complex = complexContainer

complexExample :: Int -> ComplexContainer -> Int
complexExample int container = complexAddFoo 1 container + complexAddBar 1 container

lens-core for lens providers

Presently, libraries that want to provide lenses to users can do so without incurring a dependency on lens. This is a very neat property, but could be a little bit obtuse documentation-wise.

A small amount of discussion here: diagrams/diagrams-lib#49 (comment)

Also, as soon as libraries want to provide anything more than lenses and traversals (which are definitely the most common), they definitely need to add a dependency. This could encourage library writers to use lenses instead of the more specific iso, or traversal instead of the more specific projection.

Anyway, I really don't feel very strongly about it - just putting down thoughts. Diagrams is fine with adding a lens dependency, and I don't personally anticipate needing lens-core.

Generalize the signature of Getting and IndexedGetting

As it is, when you are given a lens/traversal that you plan to use to change the type of a field, it is hard to use any getting or fold combinators on it.

I think the best compromise is to keep Getter and Fold in their two argument form and add the other two args back to Getting and IndexedGetting.

Benchmark alongside

I suppose the first step in knowing if an alternative implementation is warranted for #43 is to actually do some benchmarking.

[00:15] edwardk: Context is slow
[00:16] edwardk: maybe my fast Context comonad?
[00:16] edwardk: newtype Store c d a = Store { runStore :: forall f. Functor f => (c -> f d) -> f a }
[00:16] edwardk: i could probably use that
[00:17] edwardk: that should give back the speed lost if i come up with the right implementation
[00:17] edwardk: i'll add an issue to explore it
[00:19] mgsloan: what if it was "alongside l r = lens (\(a, a') -> (view l a, view r a')) (\(a, a') (b, b') -> (set l b a, set r b' a'))" orso
[00:20] edwardk: viewing and setting separately is probably not a win
[00:20] mgsloan: for big products it might be
[00:21] edwardk: but if you wanted to concoct an alongside benchmark i'd be happy to listen to it, and try my final Store on it as well
[00:21] mgsloan: especially if there's not much depth to l / r
[00:21] edwardk: feel like adding another benchmark to the benchmarks folder and benchmark suites?
[00:21] mgsloan: the final Store sounds good :) not sure I get it
[00:22] mgsloan: sure, could do that

Build classes for IndexedFunctor, IndexedFoldable and IndexedTraversable.

It would be nice to reduce the name clutter for the common 'traverse the polymorphic argument' case.

Problem:

For Traversable the traverse is a valid traversal, but if itraverse is a valid indexed traversal, then its not usable as the function that traverses the container with the index directly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.