Using NoImplicitPrelude language extension

This allows us to reduce CPP usage to actuall differences between
versions of libraries.

Addresses #6
This commit is contained in:
Peter Trsko 2017-01-30 19:36:54 +01:00 committed by Peter Trško
parent 751199afa9
commit 4769e9f50b
14 changed files with 178 additions and 96 deletions

View File

@ -1,7 +1,7 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer
-- Description: Freer - an extensible effects library
@ -28,12 +28,14 @@ module Control.Monad.Freer (
msplit
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative (pure)
#endif
import Control.Monad ((>>=))
import Data.Function ((.), const)
import Data.Tuple (uncurry)
import Control.Monad.Freer.Internal
runNat
:: Member m r
=> (forall a. e a -> m a) -> Eff (e ': r) w -> Eff r w

View File

@ -1,7 +1,8 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
-- |
-- Module: Control.Monad.Freer.Coroutine
-- Description: Composable coroutine effects layer.
@ -21,8 +22,13 @@ module Control.Monad.Freer.Coroutine (
runC
) where
import Control.Monad (return)
import Data.Function (($), (.))
import Data.Functor (Functor)
import Control.Monad.Freer.Internal
-- | A type representing a yielding of control
-- a: The current type
-- b: The input to the continuation function

View File

@ -1,6 +1,7 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.Cut
-- Description: An implementation of logical Cut.
@ -24,6 +25,7 @@ module Control.Monad.Freer.Cut (
import Control.Monad.Freer.Exception
import Control.Monad.Freer.Internal
data CutFalse = CutFalse
-- data Choose a b = Choose [a] b

View File

@ -1,6 +1,7 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.Exception
-- Description: An Exception effect and handler.
@ -21,28 +22,37 @@ module Control.Monad.Freer.Exception (
catchError
) where
import Control.Monad.Freer.Internal
import Control.Applicative (pure)
import Data.Either (Either(Left, Right))
import Data.Function ((.))
import Control.Monad.Freer.Internal (Eff, Member, handleRelay, interpose, send)
--------------------------------------------------------------------------------
-- Exceptions --
--------------------------------------------------------------------------------
-- | Exceptions of the type e; no resumption
newtype Exc e v = Exc e
-- | Throws an error carrying information of type e
throwError :: (Member (Exc e) r) => e -> Eff r a
-- | Exceptions of the type e; no resumption
newtype Exc e a = Exc e
-- | Throws an error carrying information of type @e@.
throwError :: Member (Exc e) effs => e -> Eff effs a
throwError e = send (Exc e)
-- | Handler for exception effects
-- If there are no exceptions thrown, returns Right If exceptions are
-- thrown and not handled, returns Left, interrupting the execution of
-- any other effect handlers.
runError :: Eff (Exc e ': r) a -> Eff r (Either e a)
runError :: Eff (Exc e ': effs) a -> Eff effs (Either e a)
runError =
handleRelay (return . Right) (\ (Exc e) _k -> return (Left e))
handleRelay (pure . Right) (\(Exc e) _k -> pure (Left e))
-- | A catcher for Exceptions. Handlers are allowed to rethrow
-- exceptions.
catchError :: Member (Exc e) r =>
Eff r a -> (e -> Eff r a) -> Eff r a
catchError m handle = interpose return (\(Exc e) _k -> handle e) m
catchError
:: Member (Exc e) effs
=> Eff effs a
-> (e -> Eff effs a)
-> Eff effs a
catchError m handle = interpose pure (\(Exc e) _k -> handle e) m

View File

@ -1,7 +1,8 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.Fresh
-- Description: Generation of fresh integers as an effect.
@ -21,22 +22,27 @@ module Control.Monad.Freer.Fresh (
runFresh'
) where
import Control.Monad.Freer.Internal
import Prelude (($!), (+))
import Control.Applicative (pure)
import Data.Int (Int)
import Control.Monad.Freer.Internal (Eff, Member, handleRelayS, send)
--------------------------------------------------------------------------------
-- Fresh --
--------------------------------------------------------------------------------
-- | Fresh effect model
data Fresh v where
data Fresh a where
Fresh :: Fresh Int
-- | Request a fresh effect
fresh :: Member Fresh r => Eff r Int
fresh :: Member Fresh effs => Eff effs Int
fresh = send Fresh
-- | Handler for Fresh effects, with an Int for a starting value
runFresh' :: Eff (Fresh ': r) w -> Int -> Eff r w
-- | Handler for 'Fresh' effects, with an 'Int' for a starting value.
runFresh' :: Eff (Fresh ': effs) a -> Int -> Eff effs a
runFresh' m s =
handleRelayS s (\_s x -> return x)
(\s' Fresh k -> (k $! s'+1) s')
m
handleRelayS s (\_s a -> pure a) (\s' Fresh k -> (k $! s' + 1) s') m

View File

@ -1,10 +1,11 @@
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- The following is needed to define MonadPlus instance. It is decidable
-- (there is no recursion!), but GHC cannot see that.
@ -53,26 +54,39 @@ module Control.Monad.Freer.Internal (
interpose,
) where
import Control.Monad
import Prelude (error)
import Control.Applicative
import Data.Open.Union
( Alternative((<|>), empty)
, Applicative((<*>), pure)
)
import Control.Monad
( Monad((>>=), return)
, MonadPlus(mplus, mzero)
, liftM2
, msum
)
import Data.Bool (Bool(False, True))
import Data.Either (Either(Left, Right))
import Data.Function (($), (.))
import Data.Functor (fmap)
import Data.Maybe (Maybe(Just, Nothing))
import Data.FTCQueue
import Data.Open.Union
-- |
-- Effectful arrow type: a function from a to b that also does effects
-- denoted by r
-- | Effectful arrow type: a function from @a@ to @b@ that also does effects
-- denoted by @r@.
type Arr r a b = a -> Eff r b
-- |
-- An effectful function from 'a' to 'b' that is a composition of
-- | An effectful function from @a@ to @b@ that is a composition of
-- several effectful functions. The paremeter r describes the overall
-- effect. The composition members are accumulated in a type-aligned
-- queue.
type Arrs r a b = FTCQueue (Eff r) a b
-- |
-- The Eff representation.
-- | The Eff representation.
--
-- Status of a coroutine (client):
-- * Val: Done with the value of type a
@ -95,25 +109,28 @@ qComp :: Arrs r a b -> (Eff r b -> Eff r' c) -> Arr r' a c
qComp g h a = h $ qApp g a
instance Functor (Eff r) where
{-# INLINE fmap #-}
fmap f (Val x) = Val (f x)
fmap f (E u q) = E u (q |> (Val . f))
{-# INLINE fmap #-}
instance Applicative (Eff r) where
{-# INLINE pure #-}
{-# INLINE (<*>) #-}
pure = Val
{-# INLINE pure #-}
Val f <*> Val x = Val $ f x
Val f <*> E u q = E u (q |> (Val . f))
E u q <*> Val x = E u (q |> (Val . ($ x)))
E u q <*> m = E u (q |> (`fmap` m))
{-# INLINE (<*>) #-}
instance Monad (Eff r) where
-- Future versions of GHC will consider any other definition as error.
return = pure
{-# INLINE return #-}
{-# INLINE (>>=) #-}
return = Val
Val x >>= k = k x
E u q >>= k = E u (q |> k)
{-# INLINE (>>=) #-}
-- | send a request and wait for a reply
send :: Member t r => t v -> Eff r v
@ -122,6 +139,7 @@ send t = E (inj t) (tsingleton Val)
--------------------------------------------------------------------------------
-- Base Effect Runner --
--------------------------------------------------------------------------------
-- | Runs a set of Effects. Requires that all effects are consumed.
-- Typically composed as follows:
-- > run . runEff1 eff1Arg . runEff2 eff2Arg1 eff2Arg2 (program)
@ -185,6 +203,7 @@ interpose ret h = loop
--------------------------------------------------------------------------------
-- Nondeterministic Choice --
--------------------------------------------------------------------------------
-- | A data type for representing nondeterminstic choice
data NonDetEff a where
MZero :: NonDetEff a

View File

@ -53,7 +53,7 @@ import Control.Monad.Freer.Internal
-- | Represents shared immutable environment of type @(e :: *)@ which is made
-- available to effectful computation.
data Reader e v where
data Reader e a where
Reader :: Reader e e
-- | Request a value of the environment.

View File

@ -36,6 +36,16 @@ import Data.Proxy (Proxy)
import Data.Tuple (fst, snd)
import Control.Monad.Freer.Internal
( Eff(E, Val)
, Member
, Union
, decomp
, prj
, qApp
, qComp
, send
, tsingleton
)
--------------------------------------------------------------------------------
@ -43,48 +53,49 @@ import Control.Monad.Freer.Internal
--------------------------------------------------------------------------------
-- | Strict State effects: one can either Get values or Put them
data State s v where
data State s a where
Get :: State s s
Put :: !s -> State s ()
-- | Retrieve state
get :: Member (State s) r => Eff r s
get :: Member (State s) effs => Eff effs s
get = send Get
-- | Store state
put :: Member (State s) r => s -> Eff r ()
put :: Member (State s) effs => s -> Eff effs ()
put s = send (Put s)
-- | Modify state
modify :: Member (State s) r => (s -> s) -> Eff r ()
modify :: Member (State s) effs => (s -> s) -> Eff effs ()
modify f = fmap f get >>= put
-- | Handler for State effects
runState :: Eff (State s ': r) w -> s -> Eff r (w,s)
runState (Val x) s = return (x,s)
runState :: Eff (State s ': effs) a -> s -> Eff effs (a, s)
runState (Val x) s = return (x, s)
runState (E u q) s = case decomp u of
Right Get -> runState (qApp q s) s
Right (Put s') -> runState (qApp q ()) s'
Left u' -> E u' (tsingleton (\x -> runState (qApp q x) s))
-- | Run a State effect, returning only the final state
execState :: Eff (State s ': r) w -> s -> Eff r s
execState :: Eff (State s ': effs) a -> s -> Eff effs s
execState st s = snd <$> runState st s
-- | Run a State effect, discarding the final state
evalState :: Eff (State s ': r) w -> s -> Eff r w
evalState :: Eff (State s ': effs) a -> s -> Eff effs a
evalState st s = fst <$> runState st s
-- |
-- An encapsulated State handler, for transactional semantics
-- The global state is updated only if the transactionState finished
-- successfully
transactionState :: forall s r w. Member (State s) r =>
Proxy s -> Eff r w -> Eff r w
-- | An encapsulated State handler, for transactional semantics. The global
-- state is updated only if the transactionState finished successfully.
transactionState
:: forall s effs a
. Member (State s) effs
=> Proxy s
-> Eff effs a
-> Eff effs a
transactionState _ m = do s <- get; loop s m
where
loop :: s -> Eff r w -> Eff r w
loop :: s -> Eff effs a -> Eff effs a
loop s (Val x) = put s >> return x
loop s (E (u :: Union r b) q) = case prj u :: Maybe (State s b) of
Just Get -> loop s (qApp q s)

View File

@ -1,7 +1,8 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.StateRW
-- Description: State effects in terms of Reader and Writer.
@ -24,16 +25,20 @@ module Control.Monad.Freer.StateRW (
ask
) where
import Control.Monad.Freer.Reader
import Control.Monad.Freer.Writer
import Control.Monad.Freer.Internal
import Control.Monad (return)
import Data.Either (Either(Left, Right))
-- | State handler, using Reader/Writer effects
runStateR :: Eff (Writer s ': Reader s ': r) w -> s -> Eff r (w,s)
import Control.Monad.Freer.Reader (Reader(Reader), ask)
import Control.Monad.Freer.Writer (Writer(Writer), tell)
import Control.Monad.Freer.Internal (Eff(E, Val), decomp, qComp, tsingleton)
-- | State handler, using 'Reader' and 'Writer' effects.
runStateR :: Eff (Writer s ': Reader s ': effs) a -> s -> Eff effs (a, s)
runStateR m s = loop s m
where
loop :: s -> Eff (Writer s ': Reader s ': r) w -> Eff r (w,s)
loop s' (Val x) = return (x,s')
loop :: s -> Eff (Writer s ': Reader s ': effs) a -> Eff effs (a, s)
loop s' (Val x) = return (x, s')
loop s' (E u q) = case decomp u of
Right (Writer o) -> k o ()
Left u' -> case decomp u' of

View File

@ -1,7 +1,8 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.Trace
-- Description: Composable Trace effects.
@ -21,10 +22,16 @@ module Control.Monad.Freer.Trace (
runTrace
) where
import Control.Monad.Freer.Internal
import Control.Monad ((>>), return)
import Data.Function ((.))
import Data.String (String)
import System.IO (IO, putStrLn)
import Control.Monad.Freer.Internal (Eff(E, Val), Member, extract, qApp, send)
-- | A Trace effect; takes a String and performs output
data Trace v where
data Trace a where
Trace :: String -> Trace ()
-- | Printing a string in a trace
@ -32,7 +39,7 @@ trace :: Member Trace r => String -> Eff r ()
trace = send . Trace
-- | An IO handler for Trace effects
runTrace :: Eff '[Trace] w -> IO w
runTrace :: Eff '[Trace] a -> IO a
runTrace (Val x) = return x
runTrace (E u q) = case extract u of
Trace s -> putStrLn s >> runTrace (qApp q ())
Trace s -> putStrLn s >> runTrace (qApp q ())

View File

@ -1,8 +1,8 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeOperators #-}
-- |
-- Module: Control.Monad.Freer.Writer
-- Description: Composable Writer effects.
@ -21,21 +21,23 @@ module Control.Monad.Freer.Writer (
runWriter
) where
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid
#endif
import Control.Applicative (pure)
import Data.Function (($))
import Data.Functor ((<$>))
import Data.Monoid (Monoid, (<>), mempty)
import Control.Monad.Freer.Internal
import Control.Monad.Freer.Internal (Eff, Member, handleRelay, send)
-- | Writer effects - send outputs to an effect environment
data Writer o x where
Writer :: o -> Writer o ()
-- | Send a change to the attached environment
tell :: Member (Writer o) r => o -> Eff r ()
tell o = send $ Writer o
-- | Writer effects - send outputs to an effect environment.
data Writer w a where
Writer :: w -> Writer w ()
-- | Simple handler for Writer effects
runWriter :: Monoid o => Eff (Writer o ': r) a -> Eff r (a,o)
runWriter = handleRelay (\x -> return (x,mempty))
(\ (Writer o) k -> k () >>= \ (x,l) -> return (x,o `mappend` l))
-- | Send a change to the attached environment.
tell :: Member (Writer w) effs => w -> Eff effs ()
tell w = send $ Writer w
-- | Simple handler for 'Writer' effects.
runWriter :: Monoid w => Eff (Writer w ': effs) a -> Eff effs (a, w)
runWriter = handleRelay (\a -> pure (a, mempty)) $ \(Writer w) k ->
(\(a, l) -> (a, w <> l)) <$> k ()

View File

@ -1,4 +1,5 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
-- |
-- Module: Data.FTCQueue
-- Description: Fast type-aligned queue optimized to effectful functions.

View File

@ -1,10 +1,11 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
@ -49,6 +50,8 @@ module Data.Open.Union
)
where
import Data.Functor (Functor(..))
#if MIN_VERSION_base(4,9,0)
import Data.Kind (Constraint)
#else

View File

@ -3,6 +3,7 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
@ -21,7 +22,14 @@
-- These are internal definitions and should be used with caution. There are no
-- guarantees that the API of this module will be preserved between minor
-- versions of this package.
module Data.Open.Union.Internal where
module Data.Open.Union.Internal
where
import Data.Bool (Bool(False, True))
import Data.Maybe (Maybe(Just, Nothing))
import Data.Either (Either(Left, Right), either)
import Data.Function ((.))
import Data.Functor (Functor(fmap))
data Union (r :: [ * -> * ]) v where