Skip to content

Commit 8ed7a95

Browse files
authored
Merge pull request #635 from phadej/natural-transformation-0.4
Use natural-transformation-0.4
2 parents 4fd31a6 + 894273d commit 8ed7a95

File tree

7 files changed

+32
-28
lines changed

7 files changed

+32
-28
lines changed

doc/tutorial/Server.lhs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,17 +1044,17 @@ If we have a function that gets us from an `m a` to an `n a`, for any `a`, what
10441044
do we have?
10451045
10461046
``` haskell ignore
1047-
newtype m :~> n = Nat { unNat :: forall a. m a -> n a}
1047+
newtype m :~> n = NT { ($$) :: forall a. m a -> n a}
10481048
```
10491049
10501050
For example:
10511051
10521052
``` haskell
1053-
listToMaybeNat :: [] :~> Maybe
1054-
listToMaybeNat = Nat listToMaybe -- from Data.Maybe
1053+
listToMaybeNT :: [] :~> Maybe
1054+
listToMaybeNT = NT listToMaybe -- from Data.Maybe
10551055
```
10561056
1057-
(`Nat` comes from "natural transformation", in case you're wondering.)
1057+
(`NT` comes from "natural transformation", in case you're wondering.)
10581058
10591059
So if you want to write handlers using another monad/type than `Handler`, say the `Reader String` monad, the first thing you have to
10601060
prepare is a function:
@@ -1066,14 +1066,14 @@ readerToHandler :: Reader String :~> Handler
10661066
Let's start with `readerToHandler'`. We obviously have to run the `Reader`
10671067
computation by supplying it with a `String`, like `"hi"`. We get an `a` out
10681068
from that and can then just `return` it into `ExceptT`. We can then just wrap
1069-
that function with the `Nat` constructor to make it have the fancier type.
1069+
that function with the `NT` constructor to make it have the fancier type.
10701070
10711071
``` haskell
10721072
readerToHandler' :: forall a. Reader String a -> Handler a
10731073
readerToHandler' r = return (runReader r "hi")
10741074
10751075
readerToHandler :: Reader String :~> Handler
1076-
readerToHandler = Nat readerToHandler'
1076+
readerToHandler = NT readerToHandler'
10771077
```
10781078
10791079
We can write some simple webservice with the handlers running in `Reader String`.

servant/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
0.10
2+
------
3+
4+
* Use `NT` from `natural-transformation` for `Enter`
5+
16
0.9.1
27
------
38

servant/servant.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ library
5858
, http-api-data >= 0.3 && < 0.4
5959
, http-media >= 0.4 && < 0.7
6060
, http-types >= 0.8 && < 0.10
61+
, natural-transformation >= 0.4 && < 0.5
6162
, mtl >= 2.0 && < 2.3
6263
, mmorph >= 1 && < 1.1
6364
, text >= 1 && < 1.3

servant/src/Servant/Utils/Enter.hs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@
88
{-# LANGUAGE TypeFamilies #-}
99
{-# LANGUAGE TypeOperators #-}
1010
{-# LANGUAGE UndecidableInstances #-}
11-
module Servant.Utils.Enter where
11+
module Servant.Utils.Enter (
12+
module Servant.Utils.Enter,
13+
-- * natural-transformation re-exports
14+
(:~>)(..),
15+
) where
1216

13-
import qualified Control.Category as C
17+
import Control.Natural
1418
import Control.Monad.Identity
1519
import Control.Monad.Morph
1620
import Control.Monad.Reader
1721
import qualified Control.Monad.State.Lazy as LState
1822
import qualified Control.Monad.State.Strict as SState
1923
import qualified Control.Monad.Writer.Lazy as LWriter
2024
import qualified Control.Monad.Writer.Strict as SWriter
21-
import Data.Typeable
2225
import Prelude ()
2326
import Prelude.Compat
2427

@@ -38,57 +41,49 @@ instance (Enter b arg ret) => Enter (a -> b) arg (a -> ret) where
3841

3942
-- ** Useful instances
4043

41-
-- | A natural transformation from @m@ to @n@. Used to `enter` particular
42-
-- datatypes.
43-
newtype m :~> n = Nat { unNat :: forall a. m a -> n a} deriving Typeable
44-
45-
instance C.Category (:~>) where
46-
id = Nat id
47-
Nat f . Nat g = Nat (f . g)
48-
4944
instance Enter (m a) (m :~> n) (n a) where
50-
enter (Nat f) = f
45+
enter (NT f) = f
5146

5247
-- | Like `lift`.
5348
liftNat :: (Control.Monad.Morph.MonadTrans t, Monad m) => m :~> t m
54-
liftNat = Nat Control.Monad.Morph.lift
49+
liftNat = NT Control.Monad.Morph.lift
5550

5651
runReaderTNat :: r -> (ReaderT r m :~> m)
57-
runReaderTNat a = Nat (`runReaderT` a)
52+
runReaderTNat a = NT (`runReaderT` a)
5853

5954
evalStateTLNat :: Monad m => s -> (LState.StateT s m :~> m)
60-
evalStateTLNat a = Nat (`LState.evalStateT` a)
55+
evalStateTLNat a = NT (`LState.evalStateT` a)
6156

6257
evalStateTSNat :: Monad m => s -> (SState.StateT s m :~> m)
63-
evalStateTSNat a = Nat (`SState.evalStateT` a)
58+
evalStateTSNat a = NT (`SState.evalStateT` a)
6459

6560
-- | Log the contents of `SWriter.WriterT` with the function provided as the
6661
-- first argument, and return the value of the @WriterT@ computation
6762
logWriterTSNat :: MonadIO m => (w -> IO ()) -> (SWriter.WriterT w m :~> m)
68-
logWriterTSNat logger = Nat $ \x -> do
63+
logWriterTSNat logger = NT $ \x -> do
6964
(a, w) <- SWriter.runWriterT x
7065
liftIO $ logger w
7166
return a
7267

7368
-- | Like `logWriterTSNat`, but for strict @WriterT@.
7469
logWriterTLNat :: MonadIO m => (w -> IO ()) -> (LWriter.WriterT w m :~> m)
75-
logWriterTLNat logger = Nat $ \x -> do
70+
logWriterTLNat logger = NT $ \x -> do
7671
(a, w) <- LWriter.runWriterT x
7772
liftIO $ logger w
7873
return a
7974

8075
-- | Like @mmorph@'s `hoist`.
8176
hoistNat :: (MFunctor t, Monad m) => (m :~> n) -> (t m :~> t n)
82-
hoistNat (Nat n) = Nat $ hoist n
77+
hoistNat (NT n) = NT $ hoist n
8378

8479
-- | Like @mmorph@'s `embed`.
8580
embedNat :: (MMonad t, Monad n) => (m :~> t n) -> (t m :~> t n)
86-
embedNat (Nat n) = Nat $ embed n
81+
embedNat (NT n) = NT $ embed n
8782

8883
-- | Like @mmorph@'s `squash`.
8984
squashNat :: (Monad m, MMonad t) => t (t m) :~> t m
90-
squashNat = Nat squash
85+
squashNat = NT squash
9186

9287
-- | Like @mmorph@'s `generalize`.
9388
generalizeNat :: Applicative m => Identity :~> m
94-
generalizeNat = Nat (pure . runIdentity)
89+
generalizeNat = NT (pure . runIdentity)

stack-ghc-7.8.4.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extra-deps:
1515
- hspec-discover-2.2.3
1616
- hspec-expectations-0.7.2
1717
- http-api-data-0.3
18+
- natural-transformation-0.4
1819
- primitive-0.6.1.0
1920
- should-not-typecheck-2.1.0
2021
- time-locale-compat-0.1.1.1

stack-ghc-8.0.1.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ packages:
88
extra-deps:
99
- http-api-data-0.3
1010
- uri-bytestring-0.2.2.0
11+
- natural-transformation-0.4
1112
flags: {}

stack.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ packages:
99
extra-deps:
1010
- http-api-data-0.3
1111
- servant-js-0.9 # needed for tutorial
12+
- natural-transformation-0.4
1213
resolver: lts-6.0

0 commit comments

Comments
 (0)