[
  {
    "path": ".ghci",
    "content": ":set -isrc\n:l src/Lets.hs\n:set prompt \">> \"\n:set -Wall\n:set -fno-warn-unused-binds\n:set -fno-warn-unused-do-bind\n:set -fno-warn-unused-imports\n:set -fno-warn-type-defaults\n:set -XScopedTypeVariables\n:set -XOverloadedStrings\n"
  },
  {
    "path": ".gitignore",
    "content": "*~\n*#*\n\n# CABAL\n/dist\n/dist-newstyle\n/cabal-dev\n/.cabal-sandbox\n/cabal.sandbox.config\n.ghc.environment.*\n\n# Haskell Program Coverage\n/.hpc\n\n# Leksah\n*.lkshs\n\n# Intellij IDEA\n/.idea\n\n# darcs\n/_darcs\n\n# ctags\nTAGS\n\n# sbt\n/project\n/target\n\n*.swp\n\n"
  },
  {
    "path": "LICENCE",
    "content": "Copyright 2012-2015 National ICT Australia Limited\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n3. Neither the name of the author nor the names of his contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\nOR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n"
  },
  {
    "path": "README.markdown",
    "content": "# Let's Lens\n\n![System-F](https://logo.systemf.com.au/systemf-450x450.png)\n\nLet's Lens presents a series of exercises, in a similar format to\n[the Data61 functional programming course material](http://github.com/data61/fp-course).\nThe subject of the exercises is around the concept of lenses, initially proposed\nby Foster et al., to solve the view-update problem of relational databases.\n\nThe theories around lenses have been advanced significantly in recent years,\nresulting in a library, implemented in Haskell, called `lens`.\n\nhttp://hackage.haskell.org/package/lens\n\nThe exercises take into account various possible goals. For example, if you wish\nto study the history of lenses, then build up to the most recent theories, it is\nbest to start at the `Lets.GetSetLens` module. If you wish to derive the\nstructure of lenses from first principles, then derive the more modern theories,\nstart at the `Lets.Lens` module.\n\nExercises can be recognised by filling in a function body that has a placeholder\nof `error \"todo: <function-name>\"`.\n\n----\n\n### Exercise modules\n\n##### `Lets.GetSetLens`\n\nThis module presents a series of exercises, representing lenses as a traditional\npair of \"`get` and `set`\" functions. This representation may be beneficial as it\neasily appeals to an intuition of \"what a lens is\", however, it is outdated. \n\nThese exercises are useful to gain an initial understanding of the problems that\nlenses solve, as well as to gain an insight into the history of lenses and how\nthe theories have developed over time.\n\n##### `Lets.StoreLens`\n\nThis series of exercises is similar to `Lets.GetSetLens`, however, using a\nslightly altered representation of a lens, based on the `Store` comonad, which\nfuses the typical `get` and `set` operations into a data structure. This\nrepresentation is described in detail in\n*Morris, Tony. \"Asymmetric Lenses in Scala.\" (2012).*\n\n##### `Lets.OpticPolyLens`\n\nThis series of exercises introduces a new representation of lenses, first\ndescribed by Twan van Laarhoven. This representation also introduces a\ngeneralisation of lenses to permit *polymorphic update* of structures.\n\n##### `Lets.Lens`\n\nThis series of exercises starts at first principles to derive the concept of a\nlens, as it was first described by Twan van Laarhoven. The derivation then goes\non to described other structures to solve various practical problems such as\n*multi-update* and *partial update*.\n\nThis representation presents a generalisation, permitting *polymorphic update*\nover structures. After lenses are derived, further concepts are introduced, such\nas `Fold`s, `Traversal`s and `Prism`s.\n\n----\n\n### Credits\n\n* Edward Kmett on the [derivation of lenses](https://github.com/ekmett/lens/wiki/Derivation)\n"
  },
  {
    "path": "Setup.hs",
    "content": "import Distribution.Simple\nmain = defaultMain\n"
  },
  {
    "path": "changelog",
    "content": "0.0.1\n\nInit\n\n"
  },
  {
    "path": "default.nix",
    "content": "{ nixpkgs ? import <nixpkgs> {}, compiler ? \"default\" }:\nlet\n  inherit (nixpkgs) pkgs;\n  haskellPackages = if compiler == \"default\"\n                       then pkgs.haskellPackages\n                       else pkgs.haskell.packages.${compiler};\n\n  tasty-hedgehog-github = pkgs.callPackage (pkgs.fetchFromGitHub {\n    owner = \"qfpl\";\n    repo = \"tasty-hedgehog\";\n    rev = \"5da389f5534943b430300a213c5ffb5d0e13459e\";\n    sha256 = \"04pmr9q70gakd327sywpxr7qp8jnl3b0y2sqxxxcj6zj2q45q38m\";\n  }) {};\n\n  modifiedHaskellPackages = haskellPackages.override {\n    overrides = self: super: {\n      tasty-hedgehog =\n        if super ? tasty-hedgehog\n        then super.tasty-hedgehog\n        else tasty-hedgehog-github;\n    };\n  };\n\n  lets-lens = modifiedHaskellPackages.callPackage ./lets-lens.nix {};\nin\n  lets-lens\n"
  },
  {
    "path": "lets-lens.cabal",
    "content": "name:                 lets-lens\nversion:              0.0.1\nlicense:              BSD3\nlicense-file:         LICENCE\nauthor:               Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>\nmaintainer:           Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>\ncopyright:            Copyright (C) 2015-2016 National ICT Australia Limited,\n                      Copyright (c) 2017-2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.\nsynopsis:             Source code for exercises on the lens concept\ncategory:             Education\ndescription:          Source code for exercises on the lens concept\nhomepage:             https://github.com/data61/lets-lens\nbug-reports:          https://github.com/data61/lets-lens/issues\ncabal-version:        >= 1.10\nbuild-type:           Simple\nextra-source-files:   changelog\n\nsource-repository     head\n  type:               git\n  location:           git@github.com:data61/lets-lens.git\n\nflag                  small_base\n  description:        Choose the new, split-up base package.\n\nlibrary\n  default-language:   Haskell2010\n\n  build-depends:      base >= 4.8 && < 5\n                      , containers >= 0.4.0.0\n\n  ghc-options:        -Wall\n                      -fno-warn-unused-binds\n                      -fno-warn-unused-do-bind\n                      -fno-warn-unused-imports\n                      -fno-warn-type-defaults\n\n  hs-source-dirs:     src\n\n  exposed-modules:    Lets\n                      Lets.Choice\n                      Lets.Data\n                      Lets.GetSetLens\n                      Lets.Lens\n                      Lets.OpticPolyLens\n                      Lets.Profunctor\n                      Lets.StoreLens\n\ntest-suite            doctests\n  type:\n                      exitcode-stdio-1.0\n\n  main-is:\n                      doctests.hs\n\n  default-language:\n                      Haskell2010\n\n  build-depends:\n                      base < 5 && >= 3\n                      , doctest >= 0.9.7\n                      , filepath >= 1.3\n                      , directory >= 1.1\n                      , QuickCheck >= 2.0\n                      , template-haskell >= 2.8\n\n  ghc-options:\n                      -Wall\n                      -threaded\n\n  hs-source-dirs:\n                      test\n"
  },
  {
    "path": "lets-lens.nix",
    "content": "{ mkDerivation, base, containers, directory, doctest, filepath\n, QuickCheck, stdenv, template-haskell\n}:\nmkDerivation {\n  pname = \"lets-lens\";\n  version = \"0.0.1\";\n  src = ./.;\n  libraryHaskellDepends = [ base containers ];\n  testHaskellDepends = [\n    base directory doctest filepath QuickCheck template-haskell\n  ];\n  homepage = \"https://github.com/data61/lets-lens\";\n  description = \"Source code for exercises on the lens concept\";\n  license = stdenv.lib.licenses.bsd3;\n}\n"
  },
  {
    "path": "shell.nix",
    "content": "{ nixpkgs ? import <nixpkgs> {}, compiler ? \"default\" }:\nlet\n  inherit (nixpkgs) pkgs;\n  drv = import ./default.nix { inherit nixpkgs compiler; };\n  drvWithTools = pkgs.haskell.lib.addBuildDepends drv [ pkgs.cabal-install ];\nin\n  if pkgs.lib.inNixShell then drvWithTools.env else drvWithTools\n"
  },
  {
    "path": "src/Lets/Choice.hs",
    "content": "module Lets.Choice (\n  Choice(..)\n) where\n\nimport Lets.Data\nimport Lets.Profunctor\n\ndiswap ::\n  Profunctor p =>\n  p (Either a b) (Either c d)\n  -> p (Either b a) (Either d c)\ndiswap =\n  let swap = either Right Left \n  in dimap swap swap\n\n-- | Map on left or right of @Either@. Only one of @left@ or @right@ needs to be\n-- provided.\nclass Profunctor p => Choice p where\n  left ::\n    p a b\n    -> p (Either a c) (Either b c)\n  left =\n    diswap . right\n\n  right ::\n    p a b\n    -> p (Either c a) (Either c b)\n  right =\n    diswap . left\n\ninstance Choice (->) where\n  left f =\n    either (Left . f) Right\n  right f =\n    either Left (Right . f)\n\ninstance Choice Tagged where\n  left (Tagged x) =\n    Tagged (Left x)\n  right (Tagged x) =\n    Tagged (Right x)\n\n"
  },
  {
    "path": "src/Lets/Data.hs",
    "content": "module Lets.Data (\n  Locality(..)\n, Address(..)\n, Person(..)\n, IntAnd(..)\n, IntOr(..)\n, fredLocality\n, fredAddress\n, fred\n, maryLocality\n, maryAddress\n, mary\n, Store(..)\n, Const (..)\n, Tagged(..)\n, Identity(..)\n, AlongsideLeft(..)\n, AlongsideRight(..)\n) where\n\nimport Control.Applicative(Applicative(..))\nimport Data.Monoid(Monoid(..))\n\ndata Locality =\n  Locality\n    String -- city\n    String -- state\n    String -- country\n  deriving (Eq, Show)  \n\ndata Address =\n  Address\n    String -- street\n    String -- suburb\n    Locality\n  deriving (Eq, Show)  \n\ndata Person =\n  Person\n    Int -- age\n    String -- name\n    Address -- address\n  deriving (Eq, Show)\n\ndata IntAnd a =\n  IntAnd\n    Int\n    a\n  deriving (Eq, Show)\n\ndata IntOr a =\n  IntOrIs Int\n  | IntOrIsNot a\n  deriving (Eq, Show)\n\nfredLocality ::\n  Locality\nfredLocality =\n  Locality\n    \"Fredmania\"\n    \"New South Fred\"\n    \"Fredalia\"\n\nfredAddress ::\n  Address\nfredAddress =\n  Address\n    \"15 Fred St\"\n    \"Fredville\"\n    fredLocality\n\nfred ::\n  Person\nfred =\n  Person\n    24\n    \"Fred\"\n    fredAddress\n\nmaryLocality ::\n  Locality\nmaryLocality =\n  Locality\n    \"Mary Mary\"\n    \"Western Mary\"\n    \"Maristan\"\n\nmaryAddress ::\n  Address\nmaryAddress =\n  Address\n    \"83 Mary Ln\"\n    \"Maryland\"\n    maryLocality\n\nmary ::\n  Person\nmary =\n  Person\n    28\n    \"Mary\"\n    maryAddress\n\n----\n\ndata Store s a =\n  Store\n    (s -> a)\n    s\n\ndata Const a b =\n  Const {\n    getConst :: \n      a\n  }\n  deriving (Eq, Show)\n\ninstance Functor (Const a) where\n  fmap _ (Const a) =\n    Const a\n\ninstance Monoid a => Applicative (Const a) where\n  pure _ =\n    Const mempty\n  Const f <*> Const a =\n    Const (f `mappend` a)\n\ndata Tagged a b = \n  Tagged {\n    getTagged ::\n      b\n  }\n  deriving (Eq, Show)\n\ninstance Functor (Tagged a) where\n  fmap f (Tagged b) =\n    Tagged (f b)\n\ninstance Applicative (Tagged a) where\n  pure =\n    Tagged\n  Tagged f <*> Tagged a =\n    Tagged (f a)\n\ndata Identity a =\n  Identity {\n    getIdentity ::\n      a\n  }\n  deriving (Eq, Show)\n\ninstance Functor Identity where\n  fmap f (Identity a) =\n    Identity (f a)\n\ninstance Applicative Identity where\n  pure =\n    Identity\n  Identity f <*> Identity a =\n    Identity (f a)\n\ndata AlongsideLeft f b a =\n  AlongsideLeft {\n    getAlongsideLeft :: \n      f (a, b)\n  }\n\ninstance Functor f => Functor (AlongsideLeft f b) where\n  fmap f (AlongsideLeft x) =\n    AlongsideLeft (fmap (\\(a, b) -> (f a, b)) x)\n\ndata AlongsideRight f a b =\n  AlongsideRight {\n    getAlongsideRight ::\n      f (a, b)\n  }\n\ninstance Functor f => Functor (AlongsideRight f a) where\n  fmap f (AlongsideRight x) =\n    AlongsideRight (fmap (\\(a, b) -> (a, f b)) x)\n"
  },
  {
    "path": "src/Lets/GetSetLens.hs",
    "content": "module Lets.GetSetLens (\n  Lens(..)\n, getsetLaw\n, setgetLaw\n, setsetLaw\n, get\n, set\n, modify\n, (%~)\n, (.~)\n, fmodify\n, (|=)\n, fstL\n, sndL\n, mapL\n, setL\n, compose\n, (|.)\n, identity\n, product\n, (***)\n, choice\n, (|||)\n, cityL\n, countryL\n, streetL\n, suburbL\n, localityL\n, ageL\n, nameL\n, addressL\n, getSuburb\n, setStreet\n, getAgeAndCountry\n, setCityAndLocality\n, getSuburbOrCity\n, setStreetOrState\n, modifyCityUppercase\n) where\n\nimport Control.Applicative(Applicative((<*>)))\nimport Data.Char(toUpper)\nimport Data.Map(Map)\nimport qualified Data.Map as Map(insert, delete, lookup)\nimport Data.Set(Set)\nimport qualified Data.Set as Set(insert, delete, member)\nimport Lets.Data(Person(Person), Locality(Locality), Address(Address))\nimport Prelude hiding (product)\n\n-- $setup\n-- >>> import qualified Data.Map as Map(fromList)\n-- >>> import qualified Data.Set as Set(fromList)\n-- >>> import Data.Bool(bool)\n-- >>> import Data.Char(ord)\n-- >>> import Lets.Data\n\ndata Lens a b =\n  Lens\n    (a -> b -> a)\n    (a -> b)\n\n-- |\n--\n-- >>> get fstL (0 :: Int, \"abc\")\n-- 0\n--\n-- >>> get sndL (\"abc\", 0 :: Int)\n-- 0\n--\n-- prop> let types = (x :: Int, y :: String) in get fstL (x, y) == x\n--\n-- prop> let types = (x :: Int, y :: String) in get sndL (x, y) == y\nget ::\n  Lens a b\n  -> a\n  -> b\nget (Lens _ g) =\n  g\n\n-- |\n--\n-- >>> set fstL (0 :: Int, \"abc\") 1\n-- (1,\"abc\")\n--\n-- >>> set sndL (\"abc\", 0 :: Int) 1\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (z, y)\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (x, z)\nset ::\n  Lens a b\n  -> a \n  -> b\n  -> a\nset (Lens s _) a =\n  s a\n\n-- | The get/set law of lenses. This function should always return @True@.\ngetsetLaw ::\n  Eq a =>\n  Lens a b\n  -> a\n  -> Bool\ngetsetLaw l =\n  \\a -> set l a (get l a) == a\n  \n-- | The set/get law of lenses. This function should always return @True@.\nsetgetLaw ::\n  Eq b =>\n  Lens a b\n  -> a\n  -> b\n  -> Bool\nsetgetLaw l a b =\n  get l (set l a b) == b\n  \n-- | The set/set law of lenses. This function should always return @True@.\nsetsetLaw ::\n  Eq a =>\n  Lens a b\n  -> a\n  -> b\n  -> b\n  -> Bool\nsetsetLaw l a b1 b2 =\n  set l (set l a b1) b2 == set l a b2\n\n----\n\n-- |\n--\n-- >>> modify fstL (+1) (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> modify sndL (+1) (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in modify fstL id (x, y) == (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in modify sndL id (x, y) == (x, y)\nmodify ::\n  Lens a b\n  -> (b -> b)\n  -> a\n  -> a\nmodify =\n  error \"todo: modify\"\n\n-- | An alias for @modify@.\n(%~) ::\n  Lens a b\n  -> (b -> b)\n  -> a\n  -> a\n(%~) =\n  modify\n\ninfixr 4 %~\n\n-- |\n--\n-- >>> fstL .~ 1 $ (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> sndL .~ 1 $ (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (fstL .~ z $ (x, y))\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (sndL .~ z $ (x, y))\n(.~) ::\n  Lens a b\n  -> b\n  -> a\n  -> a\n(.~) =\n  error \"todo: (.~)\"\n\ninfixl 5 .~\n\n-- |\n--\n-- >>> fmodify fstL (+) (5 :: Int, \"abc\") 8\n-- (13,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (10, \"abc\")\n-- Just (20,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (11, \"abc\")\n-- Nothing\nfmodify ::\n  Functor f =>\n  Lens a b\n  -> (b -> f b)\n  -> a\n  -> f a\nfmodify =\n  error \"todo: fmodify\"\n\n-- |\n--\n-- >>> fstL |= Just 3 $ (7, \"abc\")\n-- Just (3,\"abc\")\n--\n-- >>> (fstL |= (+1) $ (3, \"abc\")) 17\n-- (18,\"abc\")\n(|=) ::\n  Functor f =>\n  Lens a b\n  -> f b\n  -> a\n  -> f a\n(|=) =\n  error \"todo: (|=)\"\n\ninfixl 5 |=\n\n-- |\n--\n-- >>> modify fstL (*10) (3, \"abc\")\n-- (30,\"abc\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw fstL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw fstL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw fstL (x, y) z\nfstL ::\n  Lens (x, y) x\nfstL =\n  error \"todo: fstL\"\n\n-- |\n--\n-- >>> modify sndL (++ \"def\") (13, \"abc\")\n-- (13,\"abcdef\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw sndL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw sndL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw sndL (x, y) z\nsndL ::\n  Lens (x, y) y\nsndL =\n  error \"todo: sndL\"\n\n-- |\n--\n-- >>> get (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Just 'c'\n--\n-- >>> get (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Nothing\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'X'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(33,'X')]\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d')]\nmapL ::\n  Ord k =>\n  k\n  -> Lens (Map k v) (Maybe v)\nmapL =\n  error \"todo: mapL\"\n\n-- |\n--\n-- >>> get (setL 3) (Set.fromList [1..5])\n-- True\n--\n-- >>> get (setL 33) (Set.fromList [1..5])\n-- False\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5]\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) False\n-- fromList [1,2,4,5]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5,33]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) False\n-- fromList [1,2,3,4,5]\nsetL ::\n  Ord k =>\n  k\n  -> Lens (Set k) Bool\nsetL =\n  error \"todo: setL\"\n\n-- |\n--\n-- >>> get (compose fstL sndL) (\"abc\", (7, \"def\"))\n-- 7\n--\n-- >>> set (compose fstL sndL) (\"abc\", (7, \"def\")) 8\n-- (\"abc\",(8,\"def\"))\ncompose ::\n  Lens b c\n  -> Lens a b\n  -> Lens a c\ncompose =\n  error \"todo: compose\"\n\n-- | An alias for @compose@.\n(|.) ::\n  Lens b c\n  -> Lens a b\n  -> Lens a c\n(|.) =\n  compose\n\ninfixr 9 |.\n\n-- |\n--\n-- >>> get identity 3\n-- 3\n--\n-- >>> set identity 3 4\n-- 4\nidentity ::\n  Lens a a\nidentity =\n  error \"todo: identity\"\n\n-- |\n--\n-- >>> get (product fstL sndL) ((\"abc\", 3), (4, \"def\"))\n-- (\"abc\",\"def\")\n--\n-- >>> set (product fstL sndL) ((\"abc\", 3), (4, \"def\")) (\"ghi\", \"jkl\")\n-- ((\"ghi\",3),(4,\"jkl\"))\nproduct ::\n  Lens a b\n  -> Lens c d\n  -> Lens (a, c) (b, d)\nproduct =\n  error \"todo: product\"\n\n-- | An alias for @product@.\n(***) ::\n  Lens a b\n  -> Lens c d\n  -> Lens (a, c) (b, d)\n(***) =\n  product\n\ninfixr 3 ***\n\n-- |\n--\n-- >>> get (choice fstL sndL) (Left (\"abc\", 7))\n-- \"abc\"\n--\n-- >>> get (choice fstL sndL) (Right (\"abc\", 7))\n-- 7\n--\n-- >>> set (choice fstL sndL) (Left (\"abc\", 7)) \"def\"\n-- Left (\"def\",7)\n--\n-- >>> set (choice fstL sndL) (Right (\"abc\", 7)) 8\n-- Right (\"abc\",8)\nchoice ::\n  Lens a x\n  -> Lens b x\n  -> Lens (Either a b) x\nchoice =\n  error \"todo: choice\"\n\n-- | An alias for @choice@.\n(|||) ::\n  Lens a x\n  -> Lens b x\n  -> Lens (Either a b) x\n(|||) =\n  choice\n\ninfixr 2 |||\n\n----\n\ncityL ::\n  Lens Locality String\ncityL =\n  Lens\n    (\\(Locality _ t y) c -> Locality c t y)\n    (\\(Locality c _ _) -> c)\n\nstateL ::\n  Lens Locality String\nstateL =\n  Lens\n    (\\(Locality c _ y) t -> Locality c t y)\n    (\\(Locality _ t _) -> t)\n\ncountryL ::\n  Lens Locality String\ncountryL =\n  Lens\n    (\\(Locality c t _) y -> Locality c t y)\n    (\\(Locality _ _ y) -> y)\n\nstreetL ::\n  Lens Address String\nstreetL =\n  Lens\n    (\\(Address _ s l) t -> Address t s l)\n    (\\(Address t _ _) -> t)\n\nsuburbL ::\n  Lens Address String\nsuburbL =\n  Lens\n    (\\(Address t _ l) s -> Address t s l)\n    (\\(Address _ s _) -> s)\n\nlocalityL ::\n  Lens Address Locality\nlocalityL =\n  Lens\n    (\\(Address t s _) l -> Address t s l)\n    (\\(Address _ _ l) -> l)\n\nageL ::\n  Lens Person Int\nageL =\n  Lens\n    (\\(Person _ n d) a -> Person a n d)\n    (\\(Person a _ _) -> a)\n\nnameL ::\n  Lens Person String\nnameL =\n  Lens\n    (\\(Person a _ d) n -> Person a n d)\n    (\\(Person _ n _) -> n)\n\naddressL ::\n  Lens Person Address\naddressL =\n  Lens\n    (\\(Person a n _) d -> Person a n d)\n    (\\(Person _ _ d) -> d)\n\n-- |\n--\n-- >>> getSuburb fred\n-- \"Fredville\"\n--\n-- >>> getSuburb mary\n-- \"Maryland\"\ngetSuburb ::\n  Person\n  -> String\ngetSuburb =\n  error \"todo: getSuburb\"\n\n-- |\n--\n-- >>> setStreet fred \"Some Other St\"\n-- Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setStreet mary \"Some Other St\"\n-- Person 28 \"Mary\" (Address \"Some Other St\" \"Maryland\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetStreet ::\n  Person\n  -> String\n  -> Person\nsetStreet =\n  error \"todo: setStreet\"\n\n-- |\n--\n-- >>> getAgeAndCountry (fred, maryLocality)\n-- (24,\"Maristan\")\n--\n-- >>> getAgeAndCountry (mary, fredLocality)\n-- (28,\"Fredalia\")\ngetAgeAndCountry ::\n  (Person, Locality)\n  -> (Int, String)\ngetAgeAndCountry =\n  error \"todo: getAgeAndCountry\"\n\n-- |\n--\n-- >>> setCityAndLocality (fred, maryAddress) (\"Some Other City\", fredLocality)\n-- (Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"Some Other City\" \"New South Fred\" \"Fredalia\")),Address \"83 Mary Ln\" \"Maryland\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setCityAndLocality (mary, fredAddress) (\"Some Other City\", maryLocality)\n-- (Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"Some Other City\" \"Western Mary\" \"Maristan\")),Address \"15 Fred St\" \"Fredville\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetCityAndLocality ::\n  (Person, Address) -> (String, Locality) -> (Person, Address)\nsetCityAndLocality =\n  error \"todo: setCityAndLocality\"\n  \n-- |\n--\n-- >>> getSuburbOrCity (Left maryAddress)\n-- \"Maryland\"\n--\n-- >>> getSuburbOrCity (Right fredLocality)\n-- \"Fredmania\"\ngetSuburbOrCity ::\n  Either Address Locality\n  -> String\ngetSuburbOrCity =\n  error \"todo: getSuburbOrCity\"\n\n-- |\n--\n-- >>> setStreetOrState (Right maryLocality) \"Some Other State\"\n-- Right (Locality \"Mary Mary\" \"Some Other State\" \"Maristan\")\n--\n-- >>> setStreetOrState (Left fred) \"Some Other St\"\n-- Left (Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\")))\nsetStreetOrState ::\n  Either Person Locality\n  -> String\n  -> Either Person Locality\nsetStreetOrState =\n  error \"todo: setStreetOrState\"\n\n-- |\n--\n-- >>> modifyCityUppercase fred\n-- Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"FREDMANIA\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> modifyCityUppercase mary\n-- Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"MARY MARY\" \"Western Mary\" \"Maristan\"))\nmodifyCityUppercase ::\n  Person\n  -> Person\nmodifyCityUppercase =\n  error \"todo: modifyCityUppercase\"\n"
  },
  {
    "path": "src/Lets/Lens.hs",
    "content": "{-# LANGUAGE RankNTypes #-}\n\nmodule Lets.Lens (\n  fmapT\n, over\n, fmapTAgain\n, Set\n, sets\n, mapped\n, set\n, foldMapT\n, foldMapOf\n, foldMapTAgain\n, Fold\n, folds\n, folded\n, Get\n, get\n, Traversal\n, both\n, traverseLeft\n, traverseRight\n, Traversal'\n, Lens\n, Prism\n, _Left\n, _Right\n, prism\n, _Just\n, _Nothing\n, setP\n, getP\n, Prism'\n, modify\n, (%~)\n, (.~)\n, fmodify\n, (|=)\n, fstL\n, sndL\n, mapL\n, setL\n, compose\n, (|.)\n, identity\n, product\n, (***)\n, choice\n, (|||)\n, Lens'\n, cityL\n, stateL\n, countryL\n, streetL\n, suburbL\n, localityL\n, ageL\n, nameL\n, addressL\n, intAndIntL\n, intAndL\n, getSuburb\n, setStreet\n, getAgeAndCountry\n, setCityAndLocality\n, getSuburbOrCity\n, setStreetOrState\n, modifyCityUppercase\n, modifyIntAndLengthEven\n, traverseLocality\n, intOrIntP\n, intOrP\n, intOrLengthEven\n) where\n\nimport Control.Applicative(Applicative((<*>), pure))\nimport Data.Char(toUpper)\nimport Data.Foldable(Foldable(foldMap))\nimport Data.Functor((<$>))\nimport Data.Map(Map)\nimport qualified Data.Map as Map(insert, delete, lookup)\nimport Data.Monoid(Monoid)\nimport qualified Data.Set as Set(Set, insert, delete, member)\nimport Data.Traversable(Traversable(traverse))\nimport Lets.Data(AlongsideLeft(AlongsideLeft, getAlongsideLeft), AlongsideRight(AlongsideRight, getAlongsideRight), Identity(Identity, getIdentity), Const(Const, getConst), Tagged(Tagged, getTagged), IntOr(IntOrIs, IntOrIsNot), IntAnd(IntAnd), Person(Person), Locality(Locality), Address(Address))\nimport Lets.Choice(Choice(left, right))\nimport Lets.Profunctor(Profunctor(dimap))\nimport Prelude hiding (product)\n\n-- $setup\n-- >>> import qualified Data.Map as Map(fromList)\n-- >>> import qualified Data.Set as Set(fromList)\n-- >>> import Data.Bool(bool)\n-- >>> import Data.Char(ord)\n-- >>> import Lets.Data\n\n-- Let's remind ourselves of Traversable, noting Foldable and Functor.\n--\n-- class (Foldable t, Functor t) => Traversable t where\n--   traverse ::\n--     Applicative f => \n--     (a -> f b)\n--     -> t a\n--     -> f (t b)\n\n-- | Observe that @fmap@ can be recovered from @traverse@ using @Identity@.\n--\n-- /Reminder:/ fmap :: Functor t => (a -> b) -> t a -> t b\nfmapT ::\n  Traversable t =>\n  (a -> b)\n  -> t a\n  -> t b\nfmapT =\n  error \"todo: fmapT\"\n\n-- | Let's refactor out the call to @traverse@ as an argument to @fmapT@.\nover :: \n  ((a -> Identity b) -> s -> Identity t)\n  -> (a -> b)\n  -> s\n  -> t\nover =\n  error \"todo: over\"\n\n-- | Here is @fmapT@ again, passing @traverse@ to @over@.\nfmapTAgain ::\n  Traversable t =>\n  (a -> b)\n  -> t a\n  -> t b\nfmapTAgain =\n  error \"todo: fmapTAgain\"\n\n-- | Let's create a type-alias for this type of function.\ntype Set s t a b =\n  (a -> Identity b)\n  -> s\n  -> Identity t\n\n-- | Let's write an inverse to @over@ that does the @Identity@ wrapping &\n-- unwrapping.\nsets ::\n  ((a -> b) -> s -> t)\n  -> Set s t a b  \nsets =\n  error \"todo: sets\"\n\nmapped ::\n  Functor f =>\n  Set (f a) (f b) a b\nmapped =\n  error \"todo: mapped\"\n\nset ::\n  Set s t a b\n  -> s\n  -> b\n  -> t\nset =\n  error \"todo: set\"\n\n----\n\n-- | Observe that @foldMap@ can be recovered from @traverse@ using @Const@.\n--\n-- /Reminder:/ foldMap :: (Foldable t, Monoid b) => (a -> b) -> t a -> b\nfoldMapT ::\n  (Traversable t, Monoid b) =>\n  (a -> b)\n  -> t a\n  -> b\nfoldMapT =\n  error \"todo: foldMapT\"\n\n-- | Let's refactor out the call to @traverse@ as an argument to @foldMapT@.\nfoldMapOf ::\n  ((a -> Const r b) -> s -> Const r t)\n  -> (a -> r)\n  -> s\n  -> r\nfoldMapOf =\n  error \"todo: foldMapOf\"\n\n-- | Here is @foldMapT@ again, passing @traverse@ to @foldMapOf@.\nfoldMapTAgain ::\n  (Traversable t, Monoid b) =>\n  (a -> b)\n  -> t a\n  -> b\nfoldMapTAgain =\n  error \"todo: foldMapTAgain\"\n\n-- | Let's create a type-alias for this type of function.\ntype Fold s t a b =\n  forall r.\n  Monoid r =>\n  (a -> Const r b)\n  -> s\n  -> Const r t\n\n-- | Let's write an inverse to @foldMapOf@ that does the @Const@ wrapping &\n-- unwrapping.\nfolds ::\n  ((a -> b) -> s -> t)\n  -> (a -> Const b a)\n  -> s\n  -> Const t s\nfolds =\n  error \"todo: folds\"\n\nfolded ::\n  Foldable f =>\n  Fold (f a) (f a) a a\nfolded =\n  error \"todo: folded\"\n\n----\n\n-- | @Get@ is like @Fold@, but without the @Monoid@ constraint.\ntype Get r s a =\n  (a -> Const r a)\n  -> s\n  -> Const r s\n\nget ::\n  Get a s a\n  -> s\n  -> a\nget =\n  error \"todo: get\"\n\n----\n\n-- | Let's generalise @Identity@ and @Const r@ to any @Applicative@ instance.\ntype Traversal s t a b =\n  forall f.\n  Applicative f =>\n  (a -> f b)\n  -> s\n  -> f t\n\n-- | Traverse both sides of a pair.\nboth ::\n  Traversal (a, a) (b, b) a b\nboth =\n  error \"todo: both\"\n\n-- | Traverse the left side of @Either@.\ntraverseLeft ::\n  Traversal (Either a x) (Either b x) a b\ntraverseLeft =\n  error \"todo: traverseLeft\"\n\n-- | Traverse the right side of @Either@.\ntraverseRight ::\n  Traversal (Either x a) (Either x b) a b\ntraverseRight =\n  error \"todo: traverseRight\"\n\ntype Traversal' a b =\n  Traversal a a b b\n\n----\n\n-- | @Const r@ is @Applicative@, if @Monoid r@, however, without the @Monoid@\n-- constraint (as in @Get@), the only shared abstraction between @Identity@ and\n-- @Const r@ is @Functor@.\n--\n-- Consequently, we arrive at our lens derivation:\ntype Lens s t a b =\n  forall f.\n  Functor f =>\n  (a -> f b)\n  -> s\n  -> f t\n\n----\n\n-- | A prism is a less specific type of traversal.\ntype Prism s t a b =\n  forall p f.\n  (Choice p, Applicative f) =>\n  p a (f b)\n  -> p s (f t)\n\n_Left ::\n  Prism (Either a x) (Either b x) a b\n_Left =\n  error \"todo: _Left\"\n\n_Right ::\n  Prism (Either x a) (Either x b) a b \n_Right =\n  error \"todo: _Right\"\n\nprism ::\n  (b -> t)\n  -> (s -> Either t a)\n  -> Prism s t a b\nprism =\n  error \"todo: prism\"\n\n_Just ::\n  Prism (Maybe a) (Maybe b) a b\n_Just =\n  error \"todo: _Just\"\n\n_Nothing ::\n  Prism (Maybe a) (Maybe a) () ()\n_Nothing =\n  error \"todo: _Nothing\"\n\nsetP ::\n  Prism s t a b\n  -> s\n  -> Either t a\nsetP _ _ =\n  error \"todo: setP\"\n\ngetP ::\n  Prism s t a b\n  -> b\n  -> t\ngetP _ _ =\n  error \"todo: getP\"\n\ntype Prism' a b =\n  Prism a a b b\n\n----\n\n-- |\n--\n-- >>> modify fstL (+1) (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> modify sndL (+1) (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in modify fstL id (x, y) == (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in modify sndL id (x, y) == (x, y)\nmodify ::\n  Lens s t a b\n  -> (a -> b)\n  -> s\n  -> t\nmodify _ _ _ =\n  error \"todo: modify\"\n\n-- | An alias for @modify@.\n(%~) ::\n  Lens s t a b\n  -> (a -> b)\n  -> s\n  -> t\n(%~) =\n  modify\n\ninfixr 4 %~\n\n-- |\n--\n-- >>> fstL .~ 1 $ (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> sndL .~ 1 $ (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (fstL .~ z $ (x, y))\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (sndL .~ z $ (x, y))\n(.~) ::\n  Lens s t a b\n  -> b\n  -> s\n  -> t\n(.~) _ _ _ =\n  error \"todo: (.~)\"\n\ninfixl 5 .~\n\n-- |\n--\n-- >>> fmodify fstL (+) (5 :: Int, \"abc\") 8\n-- (13,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (10, \"abc\")\n-- Just (20,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (11, \"abc\")\n-- Nothing\nfmodify ::\n  Functor f =>\n  Lens s t a b\n  -> (a -> f b)\n  -> s\n  -> f t \nfmodify _ _ _ =\n  error \"todo: fmodify\"\n\n-- |\n--\n-- >>> fstL |= Just 3 $ (7, \"abc\")\n-- Just (3,\"abc\")\n--\n-- >>> (fstL |= (+1) $ (3, \"abc\")) 17\n-- (18,\"abc\")\n(|=) ::\n  Functor f =>\n  Lens s t a b\n  -> f b\n  -> s\n  -> f t\n(|=) _ _ _ =\n  error \"todo: (|=)\"\n\ninfixl 5 |=\n\n-- |\n--\n-- >>> modify fstL (*10) (3, \"abc\")\n-- (30,\"abc\")\nfstL ::\n  Lens (a, x) (b, x) a b\nfstL =\n  error \"todo: fstL\"\n\n-- |\n--\n-- >>> modify sndL (++ \"def\") (13, \"abc\")\n-- (13,\"abcdef\")\nsndL ::\n  Lens (x, a) (x, b) a b\nsndL =\n  error \"todo: sndL\"\n\n-- |\n--\n-- To work on `Map k a`:\n--   Map.lookup :: Ord k => k -> Map k a -> Maybe a\n--   Map.insert :: Ord k => k -> a -> Map k a -> Map k a\n--   Map.delete :: Ord k => k -> Map k a -> Map k a\n--\n-- >>> get (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Just 'c'\n--\n-- >>> get (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Nothing\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'X'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(33,'X')]\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d')]\nmapL ::\n  Ord k =>\n  k\n  -> Lens (Map k v) (Map k v) (Maybe v) (Maybe v)\nmapL =\n  error \"todo: mapL\"\n\n-- |\n--\n-- To work on `Set a`:\n--   Set.insert :: Ord a => a -> Set a -> Set a\n--   Set.member :: Ord a => a -> Set a -> Bool\n--   Set.delete :: Ord a => a -> Set a -> Set a\n--\n-- >>> get (setL 3) (Set.fromList [1..5])\n-- True\n--\n-- >>> get (setL 33) (Set.fromList [1..5])\n-- False\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5]\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) False\n-- fromList [1,2,4,5]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5,33]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) False\n-- fromList [1,2,3,4,5]\nsetL ::\n  Ord k =>\n  k\n  -> Lens (Set.Set k) (Set.Set k) Bool Bool\nsetL =\n  error \"todo: setL\"\n\n-- |\n--\n-- >>> get (compose fstL sndL) (\"abc\", (7, \"def\"))\n-- 7\n--\n-- >>> set (compose fstL sndL) (\"abc\", (7, \"def\")) 8\n-- (\"abc\",(8,\"def\"))\ncompose ::\n  Lens s t a b\n  -> Lens q r s t\n  -> Lens q r a b\ncompose _ _ =\n  error \"todo: compose\"\n\n-- | An alias for @compose@.\n(|.) ::\n  Lens s t a b\n  -> Lens q r s t\n  -> Lens q r a b\n(|.) =\n  compose\n\ninfixr 9 |.\n\n-- |\n--\n-- >>> get identity 3\n-- 3\n--\n-- >>> set identity 3 4\n-- 4\nidentity ::\n  Lens a b a b\nidentity =\n  error \"todo: identity\"\n\n-- |\n--\n-- >>> get (product fstL sndL) ((\"abc\", 3), (4, \"def\"))\n-- (\"abc\",\"def\")\n--\n-- >>> set (product fstL sndL) ((\"abc\", 3), (4, \"def\")) (\"ghi\", \"jkl\")\n-- ((\"ghi\",3),(4,\"jkl\"))\nproduct ::\n  Lens s t a b\n  -> Lens q r c d\n  -> Lens (s, q) (t, r) (a, c) (b, d)\nproduct _ _ =\n  error \"todo: product\"\n\n-- | An alias for @product@.\n(***) ::\n  Lens s t a b\n  -> Lens q r c d\n  -> Lens (s, q) (t, r) (a, c) (b, d)\n(***) =\n  product\n\ninfixr 3 ***\n\n-- |\n--\n-- >>> get (choice fstL sndL) (Left (\"abc\", 7))\n-- \"abc\"\n--\n-- >>> get (choice fstL sndL) (Right (\"abc\", 7))\n-- 7\n--\n-- >>> set (choice fstL sndL) (Left (\"abc\", 7)) \"def\"\n-- Left (\"def\",7)\n--\n-- >>> set (choice fstL sndL) (Right (\"abc\", 7)) 8\n-- Right (\"abc\",8)\nchoice ::\n  Lens s t a b\n  -> Lens q r a b\n  -> Lens (Either s q) (Either t r) a b\nchoice _ _ =\n  error \"todo: choice\"\n\n-- | An alias for @choice@.\n(|||) ::\n  Lens s t a b\n  -> Lens q r a b\n  -> Lens (Either s q) (Either t r) a b\n(|||) =\n  choice\n\ninfixr 2 |||\n\n----\n\ntype Lens' a b =\n  Lens a a b b\n\ncityL ::\n  Lens' Locality String\ncityL p (Locality c t y) =\n  fmap (\\c' -> Locality c' t y) (p c)\n\nstateL ::\n  Lens' Locality String\nstateL p (Locality c t y) =\n  fmap (\\t' -> Locality c t' y) (p t)\n\ncountryL ::\n  Lens' Locality String\ncountryL p (Locality c t y) =\n  fmap (\\y' -> Locality c t y') (p y)\n\nstreetL ::\n  Lens' Address String\nstreetL p (Address t s l) =\n  fmap (\\t' -> Address t' s l) (p t)\n\nsuburbL ::\n  Lens' Address String\nsuburbL p (Address t s l) =\n  fmap (\\s' -> Address t s' l) (p s)\n\nlocalityL ::\n  Lens' Address Locality\nlocalityL p (Address t s l) =\n  fmap (\\l' -> Address t s l') (p l)\n\nageL ::\n  Lens' Person Int\nageL p (Person a n d) =\n  fmap (\\a' -> Person a' n d) (p a)\n\nnameL ::\n  Lens' Person String\nnameL p (Person a n d) =\n  fmap (\\n' -> Person a n' d) (p n)\n\naddressL ::\n  Lens' Person Address\naddressL p (Person a n d) =\n  fmap (\\d' -> Person a n d') (p d)\n\nintAndIntL ::\n  Lens' (IntAnd a) Int\nintAndIntL p (IntAnd n a) =\n  fmap (\\n' -> IntAnd n' a) (p n)\n\n-- lens for polymorphic update\nintAndL ::\n  Lens (IntAnd a) (IntAnd b) a b\nintAndL p (IntAnd n a) =\n  fmap (\\a' -> IntAnd n a') (p a)\n\n-- |\n--\n-- >>> getSuburb fred\n-- \"Fredville\"\n--\n-- >>> getSuburb mary\n-- \"Maryland\"\ngetSuburb ::\n  Person\n  -> String\ngetSuburb =\n  error \"todo: getSuburb\"\n\n-- |\n--\n-- >>> setStreet fred \"Some Other St\"\n-- Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setStreet mary \"Some Other St\"\n-- Person 28 \"Mary\" (Address \"Some Other St\" \"Maryland\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetStreet ::\n  Person\n  -> String\n  -> Person\nsetStreet =\n  error \"todo: setStreet\"\n\n-- |\n--\n-- >>> getAgeAndCountry (fred, maryLocality)\n-- (24,\"Maristan\")\n--\n-- >>> getAgeAndCountry (mary, fredLocality)\n-- (28,\"Fredalia\")\ngetAgeAndCountry ::\n  (Person, Locality)\n  -> (Int, String)\ngetAgeAndCountry =\n  error \"todo: getAgeAndCountry\"\n\n-- |\n--\n-- >>> setCityAndLocality (fred, maryAddress) (\"Some Other City\", fredLocality)\n-- (Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"Some Other City\" \"New South Fred\" \"Fredalia\")),Address \"83 Mary Ln\" \"Maryland\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setCityAndLocality (mary, fredAddress) (\"Some Other City\", maryLocality)\n-- (Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"Some Other City\" \"Western Mary\" \"Maristan\")),Address \"15 Fred St\" \"Fredville\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetCityAndLocality ::\n  (Person, Address) -> (String, Locality) -> (Person, Address)\nsetCityAndLocality =\n  error \"todo: setCityAndLocality\"\n  \n-- |\n--\n-- >>> getSuburbOrCity (Left maryAddress)\n-- \"Maryland\"\n--\n-- >>> getSuburbOrCity (Right fredLocality)\n-- \"Fredmania\"\ngetSuburbOrCity ::\n  Either Address Locality\n  -> String\ngetSuburbOrCity =\n  error \"todo: getSuburbOrCity\"\n\n-- |\n--\n-- >>> setStreetOrState (Right maryLocality) \"Some Other State\"\n-- Right (Locality \"Mary Mary\" \"Some Other State\" \"Maristan\")\n--\n-- >>> setStreetOrState (Left fred) \"Some Other St\"\n-- Left (Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\")))\nsetStreetOrState ::\n  Either Person Locality\n  -> String\n  -> Either Person Locality\nsetStreetOrState =\n  error \"todo: setStreetOrState\"\n\n-- |\n--\n-- >>> modifyCityUppercase fred\n-- Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"FREDMANIA\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> modifyCityUppercase mary\n-- Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"MARY MARY\" \"Western Mary\" \"Maristan\"))\nmodifyCityUppercase ::\n  Person\n  -> Person\nmodifyCityUppercase =\n  error \"todo: modifyCityUppercase\"\n\n-- |\n--\n-- >>> modifyIntAndLengthEven (IntAnd 10 \"abc\")\n-- IntAnd 10 False\n--\n-- >>> modifyIntAndLengthEven (IntAnd 10 \"abcd\")\n-- IntAnd 10 True\nmodifyIntAndLengthEven ::\n  IntAnd [a]\n  -> IntAnd Bool\nmodifyIntAndLengthEven =\n  error \"todo: modifyIntAndLengthEven\"\n\n----\n\n-- |\n--\n-- >>> over traverseLocality (map toUpper) (Locality \"abc\" \"def\" \"ghi\")\n-- Locality \"ABC\" \"DEF\" \"GHI\"\ntraverseLocality ::\n  Traversal' Locality String\ntraverseLocality =\n  error \"todo: traverseLocality\"\n\n-- |\n--\n-- >>> over intOrIntP (*10) (IntOrIs 3)\n-- IntOrIs 30\n--\n-- >>> over intOrIntP (*10) (IntOrIsNot \"abc\")\n-- IntOrIsNot \"abc\"\nintOrIntP ::\n  Prism' (IntOr a) Int\nintOrIntP =\n  error \"todo: intOrIntP\"\n\nintOrP ::\n  Prism (IntOr a) (IntOr b) a b\nintOrP =\n  error \"todo: intOrP\"\n\n-- |\n--\n-- >> intOrLengthEven (IntOrIsNot \"abc\")\n-- IntOrIsNot False\n--\n-- >>> intOrLengthEven (IntOrIsNot \"abcd\")\n-- IntOrIsNot True\n--\n-- >>> intOrLengthEven (IntOrIs 10)\n-- IntOrIs 10\nintOrLengthEven ::\n  IntOr [a]\n  -> IntOr Bool\nintOrLengthEven =\n  error \"todo: intOrLengthEven\"\n"
  },
  {
    "path": "src/Lets/OpticPolyLens.hs",
    "content": "{-# LANGUAGE RankNTypes #-}\n\nmodule Lets.OpticPolyLens (\n  Lens(..)\n, getsetLaw\n, setgetLaw\n, setsetLaw\n, get\n, set\n, modify\n, (%~)\n, (.~)\n, fmodify\n, (|=)\n, fstL\n, sndL\n, mapL\n, setL\n, compose\n, (|.)\n, identity\n, product\n, (***)\n, choice\n, (|||)\n, cityL\n, countryL\n, streetL\n, suburbL\n, localityL\n, ageL\n, nameL\n, addressL\n, intAndIntL\n, intAndL\n, getSuburb\n, setStreet\n, getAgeAndCountry\n, setCityAndLocality\n, getSuburbOrCity\n, setStreetOrState\n, modifyCityUppercase\n, modifyIntandLengthEven\n) where\n\nimport Data.Char(toUpper)\nimport Data.Map(Map)\nimport qualified Data.Map as Map(insert, delete, lookup)\nimport Data.Set(Set)\nimport qualified Data.Set as Set(insert, delete, member)\nimport Lets.Data(AlongsideLeft(AlongsideLeft, getAlongsideLeft), AlongsideRight(AlongsideRight, getAlongsideRight), Identity(Identity, getIdentity), Const(Const, getConst), IntAnd(IntAnd), Person(Person), Locality(Locality), Address(Address))\nimport Prelude hiding (product)\n\n-- $setup\n-- >>> import qualified Data.Map as Map(fromList)\n-- >>> import qualified Data.Set as Set(fromList)\n-- >>> import Data.Bool(bool)\n-- >>> import Data.Char(ord)\n-- >>> import Lets.Data\n\ndata Lens s t a b =\n  Lens\n    (forall f. Functor f => (a -> f b) -> s -> f t)\n\nget ::\n  Lens s t a b\n  -> s\n  -> a\nget (Lens r) =\n  getConst . r Const\n\nset ::\n  Lens s t a b\n  -> s\n  -> b\n  -> t\nset (Lens r) a b =\n  getIdentity (r (const (Identity b)) a)\n\n-- | The get/set law of lenses. This function should always return @True@.\ngetsetLaw ::\n  Eq s =>\n  Lens s s a a\n  -> s\n  -> Bool\ngetsetLaw l =\n  \\a -> set l a (get l a) == a\n\n-- | The set/get law of lenses. This function should always return @True@.\nsetgetLaw ::\n  Eq a =>\n  Lens s s a a\n  -> s\n  -> a\n  -> Bool\nsetgetLaw l a b =\n  get l (set l a b) == b\n\n-- | The set/set law of lenses. This function should always return @True@.\nsetsetLaw ::\n  Eq s =>\n  Lens s s a b\n  -> s\n  -> b\n  -> b\n  -> Bool \nsetsetLaw l a b1 b2 =\n  set l (set l a b1) b2 == set l a b2\n\n----\n\n-- |\n--\n-- >>> modify fstL (+1) (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> modify sndL (+1) (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in modify fstL id (x, y) == (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in modify sndL id (x, y) == (x, y)\nmodify ::\n  Lens s t a b\n  -> (a -> b)\n  -> s\n  -> t\nmodify =\n  error \"todo: modify\"\n\n-- | An alias for @modify@.\n(%~) ::\n  Lens s t a b\n  -> (a -> b)\n  -> s\n  -> t\n(%~) =\n  modify\n\ninfixr 4 %~\n\n-- |\n--\n-- >>> fstL .~ 1 $ (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> sndL .~ 1 $ (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (fstL .~ z $ (x, y))\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (sndL .~ z $ (x, y))\n(.~) ::\n  Lens s t a b\n  -> b\n  -> s\n  -> t\n(.~) =\n  error \"todo: (.~)\"\n\ninfixl 5 .~\n\n-- |\n--\n-- >>> fmodify fstL (+) (5 :: Int, \"abc\") 8\n-- (13,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (10, \"abc\")\n-- Just (20,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (11, \"abc\")\n-- Nothing\nfmodify ::\n  Functor f =>\n  Lens s t a b\n  -> (a -> f b)\n  -> s\n  -> f t \nfmodify =\n  error \"todo: fmodify\"\n\n-- |\n--\n-- >>> fstL |= Just 3 $ (7, \"abc\")\n-- Just (3,\"abc\")\n--\n-- >>> (fstL |= (+1) $ (3, \"abc\")) 17\n-- (18,\"abc\")\n(|=) ::\n  Functor f =>\n  Lens s t a b\n  -> f b\n  -> s\n  -> f t\n(|=) =\n  error \"todo: (|=)\"\n\ninfixl 5 |=\n\n-- |\n--\n-- >>> modify fstL (*10) (3, \"abc\")\n-- (30,\"abc\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw fstL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw fstL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw fstL (x, y) z\nfstL ::\n  Lens (a, x) (b, x) a b\nfstL =\n  error \"todo: fstL\"\n\n-- |\n--\n-- >>> modify sndL (++ \"def\") (13, \"abc\")\n-- (13,\"abcdef\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw sndL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw sndL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw sndL (x, y) z\nsndL ::\n  Lens (x, a) (x, b) a b\nsndL =\n  error \"todo: sndL\"\n\n-- |\n--\n-- >>> get (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Just 'c'\n--\n-- >>> get (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Nothing\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'X'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(33,'X')]\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d')]\nmapL ::\n  Ord k =>\n  k\n  -> Lens (Map k v) (Map k v) (Maybe v) (Maybe v)\nmapL =\n  error \"todo: mapL\"\n\n-- |\n--\n-- >>> get (setL 3) (Set.fromList [1..5])\n-- True\n--\n-- >>> get (setL 33) (Set.fromList [1..5])\n-- False\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5]\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) False\n-- fromList [1,2,4,5]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5,33]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) False\n-- fromList [1,2,3,4,5]\nsetL ::\n  Ord k =>\n  k\n  -> Lens (Set k) (Set k) Bool Bool\nsetL =\n  error \"todo: setL\"\n\n-- |\n--\n-- >>> get (compose fstL sndL) (\"abc\", (7, \"def\"))\n-- 7\n--\n-- >>> set (compose fstL sndL) (\"abc\", (7, \"def\")) 8\n-- (\"abc\",(8,\"def\"))\ncompose ::\n  Lens s t a b\n  -> Lens q r s t\n  -> Lens q r a b\ncompose =\n  error \"todo: compose\"\n\n-- | An alias for @compose@.\n(|.) ::\n  Lens s t a b\n  -> Lens q r s t\n  -> Lens q r a b\n(|.) =\n  compose\n\ninfixr 9 |.\n\n-- |\n--\n-- >>> get identity 3\n-- 3\n--\n-- >>> set identity 3 4\n-- 4\nidentity ::\n  Lens a b a b\nidentity =\n  error \"todo: identity\"\n\n-- |\n--\n-- >>> get (product fstL sndL) ((\"abc\", 3), (4, \"def\"))\n-- (\"abc\",\"def\")\n--\n-- >>> set (product fstL sndL) ((\"abc\", 3), (4, \"def\")) (\"ghi\", \"jkl\")\n-- ((\"ghi\",3),(4,\"jkl\"))\nproduct ::\n  Lens s t a b\n  -> Lens q r c d\n  -> Lens (s, q) (t, r) (a, c) (b, d)\nproduct =\n  error \"todo: product\"\n\n-- | An alias for @product@.\n(***) ::\n  Lens s t a b\n  -> Lens q r c d\n  -> Lens (s, q) (t, r) (a, c) (b, d)\n(***) =\n  product\n\ninfixr 3 ***\n\n-- |\n--\n-- >>> get (choice fstL sndL) (Left (\"abc\", 7))\n-- \"abc\"\n--\n-- >>> get (choice fstL sndL) (Right (\"abc\", 7))\n-- 7\n--\n-- >>> set (choice fstL sndL) (Left (\"abc\", 7)) \"def\"\n-- Left (\"def\",7)\n--\n-- >>> set (choice fstL sndL) (Right (\"abc\", 7)) 8\n-- Right (\"abc\",8)\nchoice ::\n  Lens s t a b\n  -> Lens q r a b\n  -> Lens (Either s q) (Either t r) a b\nchoice =\n  error \"todo: choice\"\n\n-- | An alias for @choice@.\n(|||) ::\n  Lens s t a b\n  -> Lens q r a b\n  -> Lens (Either s q) (Either t r) a b\n(|||) =\n  choice\n\ninfixr 2 |||\n\n----\n\ntype Lens' a b =\n  Lens a a b b\n\ncityL ::\n  Lens' Locality String\ncityL =\n  Lens\n    (\\p (Locality c t y) -> fmap (\\c' -> Locality c' t y) (p c))\n\nstateL ::\n  Lens' Locality String\nstateL =\n  Lens\n    (\\p (Locality c t y) -> fmap (\\t' -> Locality c t' y) (p t))\n\ncountryL ::\n  Lens' Locality String\ncountryL =\n  Lens\n    (\\p (Locality c t y) -> fmap (\\y' -> Locality c t y') (p y))\n\nstreetL ::\n  Lens' Address String\nstreetL =\n  Lens\n    (\\p (Address t s l) -> fmap (\\t' -> Address t' s l) (p t))\n\nsuburbL ::\n  Lens' Address String\nsuburbL =\n  Lens\n    (\\p (Address t s l) -> fmap (\\s' -> Address t s' l) (p s))\n\nlocalityL ::\n  Lens' Address Locality\nlocalityL =\n  Lens\n    (\\p (Address t s l) -> fmap (\\l' -> Address t s l') (p l))\n\nageL ::\n  Lens' Person Int\nageL =\n  Lens\n    (\\p (Person a n d) -> fmap (\\a' -> Person a' n d) (p a))\n\nnameL ::\n  Lens' Person String\nnameL =\n  Lens\n    (\\p (Person a n d) -> fmap (\\n' -> Person a n' d) (p n))\n\naddressL ::\n  Lens' Person Address\naddressL =\n  Lens\n    (\\p (Person a n d) -> fmap (\\d' -> Person a n d') (p d))\n\nintAndIntL ::\n  Lens' (IntAnd a) Int\nintAndIntL =\n  Lens\n    (\\p (IntAnd n a) -> fmap (\\n' -> IntAnd n' a) (p n))\n\n-- lens for polymorphic update\nintAndL ::\n  Lens (IntAnd a) (IntAnd b) a b\nintAndL =\n  Lens\n    (\\p (IntAnd n a) -> fmap (\\a' -> IntAnd n a') (p a))\n\n-- |\n--\n-- >>> getSuburb fred\n-- \"Fredville\"\n--\n-- >>> getSuburb mary\n-- \"Maryland\"\ngetSuburb ::\n  Person\n  -> String\ngetSuburb =\n  error \"todo: getSuburb\"\n\n\n-- |\n--\n-- >>> setStreet fred \"Some Other St\"\n-- Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setStreet mary \"Some Other St\"\n-- Person 28 \"Mary\" (Address \"Some Other St\" \"Maryland\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetStreet ::\n  Person\n  -> String\n  -> Person\nsetStreet =\n  error \"todo: setStreet\"\n\n-- |\n--\n-- >>> getAgeAndCountry (fred, maryLocality)\n-- (24,\"Maristan\")\n--\n-- >>> getAgeAndCountry (mary, fredLocality)\n-- (28,\"Fredalia\")\ngetAgeAndCountry ::\n  (Person, Locality)\n  -> (Int, String)\ngetAgeAndCountry =\n  error \"todo: getAgeAndCountry\"\n\n-- |\n--\n-- >>> setCityAndLocality (fred, maryAddress) (\"Some Other City\", fredLocality)\n-- (Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"Some Other City\" \"New South Fred\" \"Fredalia\")),Address \"83 Mary Ln\" \"Maryland\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setCityAndLocality (mary, fredAddress) (\"Some Other City\", maryLocality)\n-- (Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"Some Other City\" \"Western Mary\" \"Maristan\")),Address \"15 Fred St\" \"Fredville\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetCityAndLocality ::\n  (Person, Address) -> (String, Locality) -> (Person, Address)\nsetCityAndLocality =\n  error \"todo: setCityAndLocality\"\n  \n-- |\n--\n-- >>> getSuburbOrCity (Left maryAddress)\n-- \"Maryland\"\n--\n-- >>> getSuburbOrCity (Right fredLocality)\n-- \"Fredmania\"\ngetSuburbOrCity ::\n  Either Address Locality\n  -> String\ngetSuburbOrCity =\n  get (suburbL ||| cityL)\n\n-- |\n--\n-- >>> setStreetOrState (Right maryLocality) \"Some Other State\"\n-- Right (Locality \"Mary Mary\" \"Some Other State\" \"Maristan\")\n--\n-- >>> setStreetOrState (Left fred) \"Some Other St\"\n-- Left (Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\")))\nsetStreetOrState ::\n  Either Person Locality\n  -> String\n  -> Either Person Locality\nsetStreetOrState =\n  set (streetL |. addressL ||| stateL)\n\n-- |\n--\n-- >>> modifyCityUppercase fred\n-- Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"FREDMANIA\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> modifyCityUppercase mary\n-- Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"MARY MARY\" \"Western Mary\" \"Maristan\"))\nmodifyCityUppercase ::\n  Person\n  -> Person\nmodifyCityUppercase =\n  cityL |. localityL |. addressL %~ map toUpper\n\n-- |\n--\n-- >>> modify intAndL (even . length) (IntAnd 10 \"abc\")\n-- IntAnd 10 False\n--\n-- >>> modify intAndL (even . length) (IntAnd 10 \"abcd\")\n-- IntAnd 10 True\nmodifyIntandLengthEven ::\n  IntAnd [a]\n  -> IntAnd Bool\nmodifyIntandLengthEven =\n  intAndL %~ even . length\n"
  },
  {
    "path": "src/Lets/Profunctor.hs",
    "content": "module Lets.Profunctor (\n  Profunctor(dimap)\n) where\n\nimport Lets.Data\n\n-- | A profunctor is a binary functor, with the first argument in contravariant\n-- (negative) position and the second argument in covariant (positive) position.\nclass Profunctor p where\n  dimap ::\n    (b -> a)\n    -> (c -> d)\n    -> p a c\n    -> p b d\n\ninstance Profunctor (->) where\n  dimap f g = \\h -> g . h . f\n\ninstance Profunctor Tagged where\n  dimap _ g (Tagged x) =\n    Tagged (g x)\n"
  },
  {
    "path": "src/Lets/StoreLens.hs",
    "content": "module Lets.StoreLens (\n  Store(..)\n, setS\n, getS\n, mapS\n, duplicateS\n, extendS\n, extractS\n, Lens(..)\n, getsetLaw\n, setgetLaw\n, setsetLaw\n, get\n, set\n, modify\n, (%~)\n, (.~)\n, fmodify\n, (|=)\n, fstL\n, sndL\n, mapL\n, setL\n, compose\n, (|.)\n, identity\n, product\n, (***)\n, choice\n, (|||)\n, cityL\n, stateL\n, countryL\n, streetL\n, suburbL\n, localityL\n, ageL\n, nameL\n, addressL\n, getSuburb\n, setStreet\n, getAgeAndCountry\n, setCityAndLocality\n, getSuburbOrCity\n, setStreetOrState\n, modifyCityUppercase\n) where\n\nimport Control.Applicative(Applicative((<*>)))\nimport Data.Char(toUpper)\nimport Data.Functor((<$>))\nimport Data.Map(Map)\nimport qualified Data.Map as Map(insert, delete, lookup)\nimport Data.Set(Set)\nimport qualified Data.Set as Set(insert, delete, member)\nimport Lets.Data(Store(Store), Person(Person), Locality(Locality), Address(Address))\nimport Prelude hiding (product)\n\n-- $setup\n-- >>> import qualified Data.Map as Map(fromList)\n-- >>> import qualified Data.Set as Set(fromList)\n-- >>> import Data.Bool(bool)\n-- >>> import Data.Char(ord)\n-- >>> import Lets.Data\n\nsetS ::\n  Store s a\n  -> s\n  -> a\nsetS (Store s _) =\n  s\n\ngetS ::\n  Store s a\n  -> s\ngetS (Store _ g) =\n  g\n\nmapS ::\n  (a -> b)\n  -> Store s a\n  -> Store s b\nmapS =\n  error \"todo: mapS\"\n\nduplicateS ::\n  Store s a\n  -> Store s (Store s a)\nduplicateS =\n  error \"todo: duplicateS\"\n\nextendS ::\n  (Store s a -> b)\n  -> Store s a\n  -> Store s b\nextendS =\n  error \"todo: extendS\"\n\nextractS ::\n  Store s a\n  -> a\nextractS =\n  error \"todo: extractS\"\n\n----\n\ndata Lens a b =\n  Lens\n    (a -> Store b a)\n\n-- |\n--\n-- >>> get fstL (0 :: Int, \"abc\")\n-- 0\n--\n-- >>> get sndL (\"abc\", 0 :: Int)\n-- 0\n--\n-- prop> let types = (x :: Int, y :: String) in get fstL (x, y) == x\n--\n-- prop> let types = (x :: Int, y :: String) in get sndL (x, y) == y\nget ::\n  Lens a b\n  -> a\n  -> b\nget (Lens r) =\n  getS . r\n\n-- |\n--\n-- >>> set fstL (0 :: Int, \"abc\") 1\n-- (1,\"abc\")\n--\n-- >>> set sndL (\"abc\", 0 :: Int) 1\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (z, y)\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (x, z)\nset ::\n  Lens a b\n  -> a \n  -> b\n  -> a\nset (Lens r) =\n  setS . r\n\n-- | The get/set law of lenses. This function should always return @True@.\ngetsetLaw ::\n  Eq a =>\n  Lens a b\n  -> a\n  -> Bool\ngetsetLaw l =\n  \\a -> set l a (get l a) == a\n  \n-- | The set/get law of lenses. This function should always return @True@.\nsetgetLaw ::\n  Eq b =>\n  Lens a b\n  -> a\n  -> b\n  -> Bool\nsetgetLaw l a b =\n  get l (set l a b) == b\n\n-- | The set/set law of lenses. This function should always return @True@.\nsetsetLaw ::\n  Eq a =>\n  Lens a b\n  -> a\n  -> b\n  -> b\n  -> Bool\nsetsetLaw l a b1 b2 =\n  set l (set l a b1) b2 == set l a b2\n\n----\n\n-- |\n--\n-- >>> modify fstL (+1) (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> modify sndL (+1) (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in modify fstL id (x, y) == (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in modify sndL id (x, y) == (x, y)\nmodify ::\n  Lens a b\n  -> (b -> b)\n  -> a\n  -> a\nmodify =\n  error \"todo: modify\"\n\n-- | An alias for @modify@.\n(%~) ::\n  Lens a b\n  -> (b -> b)\n  -> a\n  -> a\n(%~) =\n  modify\n\ninfixr 4 %~\n\n-- |\n--\n-- >>> fstL .~ 1 $ (0 :: Int, \"abc\")\n-- (1,\"abc\")\n--\n-- >>> sndL .~ 1 $ (\"abc\", 0 :: Int)\n-- (\"abc\",1)\n--\n-- prop> let types = (x :: Int, y :: String) in set fstL (x, y) z == (fstL .~ z $ (x, y))\n--\n-- prop> let types = (x :: Int, y :: String) in set sndL (x, y) z == (sndL .~ z $ (x, y))\n(.~) ::\n  Lens a b\n  -> b\n  -> a\n  -> a\n(.~) =\n  error \"todo: (.~)\"\n\ninfixl 5 .~\n\n-- |\n--\n-- >>> fmodify fstL (+) (5 :: Int, \"abc\") 8\n-- (13,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (10, \"abc\")\n-- Just (20,\"abc\")\n--\n-- >>> fmodify fstL (\\n -> bool Nothing (Just (n * 2)) (even n)) (11, \"abc\")\n-- Nothing\nfmodify ::\n  Functor f =>\n  Lens a b\n  -> (b -> f b)\n  -> a\n  -> f a\nfmodify =\n  error \"todo: fmodify\"\n  \n-- |\n--\n-- >>> fstL |= Just 3 $ (7, \"abc\")\n-- Just (3,\"abc\")\n--\n-- >>> (fstL |= (+1) $ (3, \"abc\")) 17\n-- (18,\"abc\")\n(|=) ::\n  Functor f =>\n  Lens a b\n  -> f b\n  -> a\n  -> f a\n(|=) =\n  error \"todo: (|=)\"\n\ninfixl 5 |=\n\n-- |\n--\n-- >>> modify fstL (*10) (3, \"abc\")\n-- (30,\"abc\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw fstL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw fstL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw fstL (x, y) z\nfstL ::\n  Lens (x, y) x\nfstL =\n  error \"todo: fstL\"\n\n-- |\n--\n-- >>> modify sndL (++ \"def\") (13, \"abc\")\n-- (13,\"abcdef\")\n--\n-- prop> let types = (x :: Int, y :: String) in getsetLaw sndL (x, y)\n--\n-- prop> let types = (x :: Int, y :: String) in setgetLaw sndL (x, y) z\n--\n-- prop> let types = (x :: Int, y :: String) in setsetLaw sndL (x, y) z\nsndL ::\n  Lens (x, y) y\nsndL =\n  error \"todo: sndL\"\n\n-- |\n--\n-- >>> get (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Just 'c'\n--\n-- >>> get (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d']))\n-- Nothing\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'X'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) (Just 'X')\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(33,'X')]\n--\n-- >>> set (mapL 3) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(4,'d')]\n--\n-- >>> set (mapL 33) (Map.fromList (map (\\c -> (ord c - 96, c)) ['a'..'d'])) Nothing\n-- fromList [(1,'a'),(2,'b'),(3,'c'),(4,'d')]\nmapL ::\n  Ord k =>\n  k\n  -> Lens (Map k v) (Maybe v)\nmapL =\n  error \"todo: mapL\"\n\n-- |\n--\n-- >>> get (setL 3) (Set.fromList [1..5])\n-- True\n--\n-- >>> get (setL 33) (Set.fromList [1..5])\n-- False\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5]\n--\n-- >>> set (setL 3) (Set.fromList [1..5]) False\n-- fromList [1,2,4,5]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) True\n-- fromList [1,2,3,4,5,33]\n--\n-- >>> set (setL 33) (Set.fromList [1..5]) False\n-- fromList [1,2,3,4,5]\nsetL ::\n  Ord k =>\n  k\n  -> Lens (Set k) Bool\nsetL =\n  error \"todo: setL\"\n\n-- |\n--\n-- >>> get (compose fstL sndL) (\"abc\", (7, \"def\"))\n-- 7\n--\n-- >>> set (compose fstL sndL) (\"abc\", (7, \"def\")) 8\n-- (\"abc\",(8,\"def\"))\ncompose ::\n  Lens b c\n  -> Lens a b\n  -> Lens a c\ncompose =\n  error \"todo: compose\"\n\n-- | An alias for @compose@.\n(|.) ::\n  Lens b c\n  -> Lens a b\n  -> Lens a c\n(|.) =\n  compose\n\ninfixr 9 |.\n\n-- |\n--\n-- >>> get identity 3\n-- 3\n--\n-- >>> set identity 3 4\n-- 4\nidentity ::\n  Lens a a\nidentity =\n  error \"todo: identity\"\n    \n-- |\n--\n-- >>> get (product fstL sndL) ((\"abc\", 3), (4, \"def\"))\n-- (\"abc\",\"def\")\n--\n-- >>> set (product fstL sndL) ((\"abc\", 3), (4, \"def\")) (\"ghi\", \"jkl\")\n-- ((\"ghi\",3),(4,\"jkl\"))\nproduct ::\n  Lens a b\n  -> Lens c d\n  -> Lens (a, c) (b, d)\nproduct =\n  error \"todo: product\"\n\n-- | An alias for @product@.\n(***) ::\n  Lens a b\n  -> Lens c d\n  -> Lens (a, c) (b, d)\n(***) =\n  product\n\ninfixr 3 ***\n\n-- |\n--\n-- >>> get (choice fstL sndL) (Left (\"abc\", 7))\n-- \"abc\"\n--\n-- >>> get (choice fstL sndL) (Right (\"abc\", 7))\n-- 7\n--\n-- >>> set (choice fstL sndL) (Left (\"abc\", 7)) \"def\"\n-- Left (\"def\",7)\n--\n-- >>> set (choice fstL sndL) (Right (\"abc\", 7)) 8\n-- Right (\"abc\",8)\nchoice ::\n  Lens a x\n  -> Lens b x\n  -> Lens (Either a b) x\nchoice =\n  error \"todo: choice\"\n\n-- | An alias for @choice@.\n(|||) ::\n  Lens a x\n  -> Lens b x\n  -> Lens (Either a b) x\n(|||) =\n  choice\n\ninfixr 2 |||\n\n----\n\ncityL ::\n  Lens Locality String\ncityL =\n  Lens\n    (\\(Locality c t y) ->\n      Store (\\c' -> Locality c' t y) c)\n\nstateL ::\n  Lens Locality String\nstateL =\n  Lens\n    (\\(Locality c t y) ->\n      Store (\\t' -> Locality c t' y) t)\n\ncountryL ::\n  Lens Locality String\ncountryL =\n  Lens\n    (\\(Locality c t y) ->\n      Store (\\y' -> Locality c t y') y)\n\nstreetL ::\n  Lens Address String\nstreetL =\n  Lens\n    (\\(Address t s l) ->\n      Store (\\t' -> Address t' s l) t)\n\nsuburbL ::\n  Lens Address String\nsuburbL =\n  Lens\n    (\\(Address t s l) ->\n      Store (\\s' -> Address t s' l) s)\n\nlocalityL ::\n  Lens Address Locality\nlocalityL =\n  Lens\n    (\\(Address t s l) ->\n      Store (\\l' -> Address t s l') l)\n\nageL ::\n  Lens Person Int\nageL =\n  Lens\n    (\\(Person a n d) ->\n      Store (\\a' -> Person a' n d) a)\n\nnameL ::\n  Lens Person String\nnameL =\n  Lens\n    (\\(Person a n d) ->\n      Store (\\n' -> Person a n' d) n)\n\naddressL ::\n  Lens Person Address\naddressL =\n  Lens\n    (\\(Person a n d) ->\n    Store (\\d' -> Person a n d') d)\n\n-- |\n--\n-- >>> getSuburb fred\n-- \"Fredville\"\n--\n-- >>> getSuburb mary\n-- \"Maryland\"\ngetSuburb ::\n  Person\n  -> String\ngetSuburb =\n  error \"todo: getSuburb\"\n\n-- |\n--\n-- >>> setStreet fred \"Some Other St\"\n-- Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setStreet mary \"Some Other St\"\n-- Person 28 \"Mary\" (Address \"Some Other St\" \"Maryland\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetStreet ::\n  Person\n  -> String\n  -> Person\nsetStreet =\n  error \"todo: setStreet\"\n\n-- |\n--\n-- >>> getAgeAndCountry (fred, maryLocality)\n-- (24,\"Maristan\")\n--\n-- >>> getAgeAndCountry (mary, fredLocality)\n-- (28,\"Fredalia\")\ngetAgeAndCountry ::\n  (Person, Locality)\n  -> (Int, String)\ngetAgeAndCountry =\n  error \"todo: getAgeAndCountry\"\n\n-- |\n--\n-- >>> setCityAndLocality (fred, maryAddress) (\"Some Other City\", fredLocality)\n-- (Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"Some Other City\" \"New South Fred\" \"Fredalia\")),Address \"83 Mary Ln\" \"Maryland\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> setCityAndLocality (mary, fredAddress) (\"Some Other City\", maryLocality)\n-- (Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"Some Other City\" \"Western Mary\" \"Maristan\")),Address \"15 Fred St\" \"Fredville\" (Locality \"Mary Mary\" \"Western Mary\" \"Maristan\"))\nsetCityAndLocality ::\n  (Person, Address) -> (String, Locality) -> (Person, Address)\nsetCityAndLocality =\n  error \"todo: setCityAndLocality\"\n  \n-- |\n--\n-- >>> getSuburbOrCity (Left maryAddress)\n-- \"Maryland\"\n--\n-- >>> getSuburbOrCity (Right fredLocality)\n-- \"Fredmania\"\ngetSuburbOrCity ::\n  Either Address Locality\n  -> String\ngetSuburbOrCity =\n  error \"todo: getSuburbOrCity\"\n\n-- |\n--\n-- >>> setStreetOrState (Right maryLocality) \"Some Other State\"\n-- Right (Locality \"Mary Mary\" \"Some Other State\" \"Maristan\")\n--\n-- >>> setStreetOrState (Left fred) \"Some Other St\"\n-- Left (Person 24 \"Fred\" (Address \"Some Other St\" \"Fredville\" (Locality \"Fredmania\" \"New South Fred\" \"Fredalia\")))\nsetStreetOrState ::\n  Either Person Locality\n  -> String\n  -> Either Person Locality\nsetStreetOrState =\n  error \"todo: setStreetOrState\"\n\n-- |\n--\n-- >>> modifyCityUppercase fred\n-- Person 24 \"Fred\" (Address \"15 Fred St\" \"Fredville\" (Locality \"FREDMANIA\" \"New South Fred\" \"Fredalia\"))\n--\n-- >>> modifyCityUppercase mary\n-- Person 28 \"Mary\" (Address \"83 Mary Ln\" \"Maryland\" (Locality \"MARY MARY\" \"Western Mary\" \"Maristan\"))\nmodifyCityUppercase ::\n  Person\n  -> Person\nmodifyCityUppercase =\n  error \"todo: modifyCityUppercase\"\n"
  },
  {
    "path": "src/Lets.hs",
    "content": "module Lets (\n  module L\n) where\n\nimport Lets.Data as L\nimport Lets.GetSetLens as L()\nimport Lets.Lens as L()\nimport Lets.OpticPolyLens as L()\nimport Lets.StoreLens as L()\n"
  },
  {
    "path": "test/doctests.hs",
    "content": "import Test.DocTest\n\nmain :: IO ()\nmain = doctest\n  [ \"-isrc\"\n  , \"src/Lets/GetSetLens.hs\"\n  , \"src/Lets/Lens.hs\"\n  , \"src/Lets/OpticPolyLens.hs\"\n  , \"src/Lets/StoreLens.hs\"\n  ]\n"
  }
]