https://github.com/tek/cornea
classy optical monadic state
https://github.com/tek/cornea
classy-optics haskell monaderror monadstate
Last synced: over 1 year ago
JSON representation
classy optical monadic state
- Host: GitHub
- URL: https://github.com/tek/cornea
- Owner: tek
- Created: 2019-03-13T18:46:43.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2022-02-05T14:42:59.000Z (over 4 years ago)
- Last Synced: 2025-02-24T09:37:33.079Z (over 1 year ago)
- Topics: classy-optics, haskell, monaderror, monadstate
- Language: Haskell
- Size: 47.9 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# Intro
Classes for accessing and mutating nested data types with corresponding adapter
classes for `MonadState`, `MonadReader` and `MonadError`. Inspired by the
[next level mtl with classy optics] talk.
[Hackage]
# Internals
Lenses and Prisms from [lens] are autogenerated with [TH] by splicing with
`deepPrisms` and `deepLenses`.
The generator recurses into single-field constructors and record fields if
there are instances of `DeepPrisms` or `DeepLenses` for their parameter types.
# Example
For `MonadError`:
```haskell
{-# LANGUAGE TemplateHaskell #-}
import Cornea (MonadDeepError(throwHoist))
import Control.Monad.Trans.Except (runExceptT)
import Data.DeepPrisms (deepPrisms)
newtype Error = Error String
newtype Inner = Inner Error
deepPrisms ''Inner
data Mid = Mid Inner
deepPrisms ''Mid
newtype Outer = Outer Mid
deepPrisms ''Outer
throwDeep :: MonadDeepError e Inner m => m ()
throwDeep = throwHoist (Inner (Error "boom"))
main :: IO (Either Outer ())
main = runExceptT throwDeep
```
In `main`, `MonadError Outer IO` and `DeepPrisms Outer Inner` are summoned.
Analogously for `MonadState`:
```haskell
{-# LANGUAGE TemplateHaskell #-}
import Cornea (MonadDeepState(get, gets, put))
import Control.Monad.Trans.State (execStateT)
import Data.DeepLenses (deepLenses)
newtype S = S Int
newtype Inner = Inner { _innerS :: S }
deepLenses ''Inner
data Mid = Mid { _midInner :: Inner }
deepLenses ''Mid
newtype Outer = Outer { _outerMid :: Mid }
deepLenses ''Outer
stateDeep :: MonadDeepState s Inner m => m ()
stateDeep = do
(Inner (S a)) <- get
b <- gets $ \(Inner (S b)) -> b
put (Inner (S (a + b + 3)))
main :: IO Outer
main = do
execStateT stateDeep (Outer (Mid (Inner (S 5))))
```
`MonadReader` works basically the same as `MonadState`.
[lens]: https://hackage.haskell.org/package/lens
[TH]: https://hackage.haskell.org/package/template-haskell
[next level mtl with classy optics]: https://github.com/gwils/next-level-mtl-with-classy-optics
[Hackage]: https://hackage.haskell.org/package/cornea