lens-family (empty) → 0.0.0
raw patch · 10 files changed
+353/−0 lines, 10 filesdep +basedep +containersdep +lens-family-coresetup-changed
Dependencies added: base, containers, lens-family-core, mtl, transformers
Files
- CHANGELOG +0/−0
- LICENSE +30/−0
- Setup.lhs +4/−0
- lens-family.cabal +49/−0
- src/Lens/Family2.hs +5/−0
- src/Lens/Family2/State.hs +5/−0
- src/Lens/Family2/State/Lazy.hs +66/−0
- src/Lens/Family2/State/Strict.hs +66/−0
- src/Lens/Family2/Stock.hs +56/−0
- src/Lens/Family2/Unchecked.hs +72/−0
+ CHANGELOG view
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright 2012 Russell O'Connor++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell+ +> import Distribution.Simple+> main = defaultMain
+ lens-family.cabal view
@@ -0,0 +1,49 @@+name: lens-family+category: Data+version: 0.0.0+license: BSD3+cabal-version: >= 1.6+license-file: LICENSE+author: Russell O'Connor+maintainer: Russell O'Connor <roconnor@theorem.ca>+stability: expermimental+copyright: Copyright (C) 2012 Russell O'Connor+synopsis: Lens Families+description: Lens Families+build-type: Simple+extra-source-files: CHANGELOG+description: This package provide optimal first class functional references+ In addition to the usual operations of getting, setting and composition, plus integration with monad state, lens families provide some unique features:+ .+ * Polymorphic updating+ .+ * Cast projection functions to read-only lenses+ .+ * Cast semantic editor combinators to modify-only lenses++source-repository head+ type: darcs+ location: http://r6.ca/lens-family+ +library+ extensions: Rank2Types+ build-depends:+ base >= 4 && < 5,+ containers >= 0.3 && < 0.5,+ transformers >= 0.2.0 && < 0.4,+ mtl >= 2.0.1 && < 2.2,+ lens-family-core >= 0.0.0 && < 0.1++ exposed-modules:+ Lens.Family2.Unchecked+ Lens.Family2+ Lens.Family2.Stock+ Lens.Family2.State.Lazy+ Lens.Family2.State.Strict+ Lens.Family2.State++ ghc-options: -Wall++ hs-source-dirs:+ src+
+ src/Lens/Family2.hs view
@@ -0,0 +1,5 @@+module Lens.Family2+ ( module Lens.Family+ ) where++import Lens.Family
+ src/Lens/Family2/State.hs view
@@ -0,0 +1,5 @@+module Lens.Family2.State+ ( module Lens.Family2.State.Lazy+ ) where++import Lens.Family2.State.Lazy
+ src/Lens/Family2/State/Lazy.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE Rank2Types #-}+-- | Lenses allow you to use fields of the state of a state monad as if they were variables in an imperative language.+-- 'access' is used to retrieve the value of a variable, and '~=' and '%=' allow you to set and modify a variable.+-- C-style compound assignments are also provided.+module Lens.Family2.State.Lazy+ ( focus+ , access+ , (%=)+ , (~=)+ , (%%=)+ -- * Compound Assignments+ , (+=), (-=), (*=)+ , (//=)+ , (&&=), (||=)+ ) where++import Control.Monad (liftM)+import Control.Monad.State.Lazy (MonadState, StateT(..), get, modify, state)+import Lens.Family (Getter, Setter, (^.), (^%=))+import qualified Lens.Family.State.Lazy as LFS+import Lens.Family2.Stock (Lens)++-- | Lift a stateful operation on a field to a stateful operation on the whole state.+-- This is a good way to call a \"subroutine\" that only needs access to part of the state.+focus :: Monad m => Lens a b -> StateT b m c -> StateT a m c+focus l = LFS.focus l++-- | Retrieve a field of the state+access :: MonadState a m => Getter a b -> m b+access l = (^. l) `liftM` get++infix 4 %=++-- | Modify a field of the state+(%=) :: MonadState a m => Setter a b -> (b -> b) -> m ()+l %= f = modify (l ^%= f)++infix 4 ~=++-- | Set a field of the state+(~=) :: MonadState a m => Setter a b -> b -> m ()+l ~= v = l %= const v++infix 4 %%=++-- | Modify a field of the state while returning another value+(%%=) :: MonadState a m => Lens a b -> (b -> (c, b)) -> m c+l %%= f = state (l f)++infixr 4 +=, -=, *=++(+=), (-=), (*=) :: (MonadState a m, Num b) => Setter a b -> b -> m ()+f += b = f %= (+ b)+f -= b = f %= subtract b+f *= b = f %= (* b)++infixr 4 //=++(//=) :: (MonadState a m, Fractional b) => Setter a b -> b -> m ()+f //= b = f %= (/ b)++infixr 4 &&=, ||=++(&&=), (||=) :: MonadState a m => Setter a Bool -> Bool -> m ()+f &&= b = f %= (&& b)+f ||= b = f %= (|| b)
+ src/Lens/Family2/State/Strict.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE Rank2Types #-}+-- | Lenses allow you to use fields of the state of a state monad as if they were variables in an imperative language.+-- 'access' is used to retrieve the value of a variable, and '~=' and '%=' allow you to set and modify a variable.+-- C-style compound assignments are also provided.+module Lens.Family2.State.Strict+ ( focus+ , access+ , (%=)+ , (~=)+ , (%%=)+ -- * Compound Assignments+ , (+=), (-=), (*=)+ , (//=)+ , (&&=), (||=)+ ) where++import Control.Monad (liftM)+import Control.Monad.State.Strict (MonadState, StateT(..), get, modify, state)+import Lens.Family (Getter, Setter, (^.), (^%=))+import qualified Lens.Family.State.Strict as LFS+import Lens.Family2.Stock (Lens)++-- | Lift a stateful operation on a field to a stateful operation on the whole state.+-- This is a good way to call a \"subroutine\" that only needs access to part of the state.+focus :: Monad m => Lens a b -> StateT b m c -> StateT a m c+focus l = LFS.focus l++-- | Retrieve a field of the state+access :: MonadState a m => Getter a b -> m b+access l = (^. l) `liftM` get++infix 4 %=++-- | Modify a field of the state+(%=) :: MonadState a m => Setter a b -> (b -> b) -> m ()+l %= f = modify (l ^%= f)++infix 4 ~=++-- | Set a field of the state+(~=) :: MonadState a m => Setter a b -> b -> m ()+l ~= v = l %= const v++infix 4 %%=++-- | Modify a field of the state while returning another value+(%%=) :: MonadState a m => Lens a b -> (b -> (c, b)) -> m c+l %%= f = state (l f)++infixr 4 +=, -=, *=++(+=), (-=), (*=) :: (MonadState a m, Num b) => Setter a b -> b -> m ()+f += b = f %= (+ b)+f -= b = f %= subtract b+f *= b = f %= (* b)++infixr 4 //=++(//=) :: (MonadState a m, Fractional b) => Setter a b -> b -> m ()+f //= b = f %= (/ b)++infixr 4 &&=, ||=++(&&=), (||=) :: MonadState a m => Setter a Bool -> Bool -> m ()+f &&= b = f %= (&& b)+f ||= b = f %= (|| b)
+ src/Lens/Family2/Stock.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE Rank2Types #-}+-- | This module contains lenses for common structures in Haskell.+-- It also contains the lens combinators 'mergeL' and '***'.+module Lens.Family2.Stock+ ( -- * Lens Combinators+ Stock.mergeL+ , (***)+ -- * Stock Lenses+ , fstL, sndL+ , funL+ , mapL, intMapL+ , setL, intSetL+ -- * Types+ , LensFamily, Lens+ ) where++import Lens.Family2.Unchecked (LensFamily, Lens, mkLens)+import qualified Lens.Family.Stock as Stock+import Lens.Family ((^.), (^=))+import qualified Data.Map as Map+import qualified Data.IntMap as IntMap+import qualified Data.Set as Set+import qualified Data.IntSet as IntSet++-- I suspect there is a more clever way to define this function.+-- | Given two lens families, make a new lens on their product.+(***) :: LensFamily a1 a1' b1 b1' -> LensFamily a2 a2' b2 b2' -> LensFamily (a1, a2) (a1', a2') (b1, b2) (b1', b2')+(***) l1 l2 f (a1, a2) = (\(v'1, v'2) -> (l1 ^= v'1 $ a1, l2 ^= v'2 $ a2)) `fmap` f (a1 ^. l1, a2 ^. l2)++-- | Lens on the first element of a pair.+fstL :: LensFamily (a, b) (a', b) a a'+fstL = Stock.fstL++-- | Lens on the second element of a pair.+sndL :: LensFamily (a, b) (a, b') b b'+sndL = Stock.sndL++-- | Lens on a given point of a function.+funL :: (Eq k) => k -> Lens (k -> v) v+funL = Stock.funL++-- | Lens on a given point of a 'Map.Map'.+mapL :: (Ord k) => k -> Lens (Map.Map k v) (Maybe v)+mapL = Stock.mapL++-- | Lens on a given point of a 'IntMap.IntMap'.+intMapL :: Int -> Lens (IntMap.IntMap v) (Maybe v)+intMapL = Stock.intMapL++-- | Lens on a given point of a 'Set.Set'.+setL :: (Ord k) => k -> Lens (Set.Set k) Bool+setL = Stock.setL++-- | Lens on a given point of a 'IntSet.IntSet'.+intSetL :: Int -> Lens IntSet.IntSet Bool+intSetL = Stock.intSetL
+ src/Lens/Family2/Unchecked.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE Rank2Types #-}+-- | /Caution/: Improper use of this module can lead to unexpected behaviour if the preconditions of the functions are not met.+-- +-- A lens family is created by separating a substructure from the rest of its structure by a functor.+-- How to create a lens family is best illustrated by the common example of a field of a record:+--+-- > data MyRecord a = MyRecord { _myA :: a, _myB :: Int }+-- >+-- > -- The use of type variables a and a' allow for polymorphic updates.+-- > myA :: LensFamily (MyRecord a) (MyRecord a') a a'+-- > myA f (MyRecord a b) = (\a' -> MyRecord a' b) `fmap` (f a)+-- >+-- > -- The field _myB is monomorphic, so we can use a plain Lens type.+-- > -- However, the structure of the function is exactly the same as for LensFamily.+-- > myB :: Lens (MyRecord a) Int+-- > myB f (MyRecord a b) = (\b' -> MyRecord a b') `fmap` (f b)+--+-- By following this template you can safely build your own lenses.+-- To use this template, you do not need anything from this module other than the type synonyms 'LensFamily' and 'Lens', and even they are optional.+-- See the @lens-family-th@ package to generate this code using Template Haskell.+--+-- You can build lenses for more than just fields of records.+-- Any value @lens :: LensFamily a a' b b'@ is well-defined when it satisfies the two van Laarhoven lens laws:+--+-- * @lens Identity === Identity@+--+-- * @+-- lens (composeCoalgebroid f g) === composeCoalgebroid (lens f) (lens g)+-- where+-- composeCoalgebroid :: (Functor f, Functor g) => (b -> f c) -> (a -> g b) -> a -> (Compose g f) c+-- composeCoalgebroid f g a = Compose $ f \`fmap\` g a === id+-- @+--+-- The functions 'mkLens' and 'mkIsoLens' can also be used to construct lenses.+-- The resulting lenses will be well-defined so long as their preconditions are satisfied.+module Lens.Family2.Unchecked+ ( mkLens+ , mkIsoLens+ -- * Types+ , LensFamily, Lens+ ) where++import qualified Lens.Family.Unchecked as LF++type LensFamily a a' b b' = forall f. Functor f => LF.LensFamily f a a' b b'+type Lens a b = LensFamily a a b b++-- | Build a lens from a @getter@ and @setter@ families.+--+-- /Caution/: In order for the generated lens family to be well-defined, you must ensure that the three lens laws hold:+-- +-- * @getter (setter a b) === b@+--+-- * @setter a (getter a) === a@+--+-- * @setter (setter a b1) b2) === setter a b2@+mkLens :: (a -> b) -- ^ getter+ -> (a -> b' -> a') -- ^ setter+ -> LensFamily a a' b b'+mkLens = LF.mkLens++-- | Build a lens from isomorphism families.+--+-- /Caution/: In order for the generated lens family to be well-defined, you must ensure that the two isomorphism laws hold:+-- +-- * @yin . yang === id@+--+-- * @yang . yin === id@+mkIsoLens :: (a -> b) -- ^ yin+ -> (b' -> a') -- ^ yang+ -> LensFamily a a' b b'+mkIsoLens = LF.mkIsoLens