Is there a library or tools for testing the laws of a custom monad? My current hacked attempt goes something like this:
Define Arbitrary1, similar to Eq1, Show1 etc.
Define a helper type that wraps Arbitrary1 as Arbitrary.
Define a test (for example) for monadic laws.
Is any of this already implemented somewhere?
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
import Data.Functor.Classes
import Data.Proxy
import Test.QuickCheck
import Test.QuickCheck.Function
import Test.QuickCheck.Poly
Define Arbitrary1 for * -> * types:
class Arbitrary1 m where
arbitrary1 :: (Arbitrary a) => Gen (m a)
shrink1 :: (Arbitrary a) => m a -> [m a]
shrink1 _ = []
And a helper wrapper so that we can use functions that work with Arbitrary:
newtype Action m a = Action { getAction :: m a }
instance (Arbitrary a, Arbitrary1 m) => Arbitrary (Action m a) where
arbitrary = Action <$> arbitrary1
shrink = map Action . shrink1 . getAction
instance (Show a, Show1 m) => Show (Action m a) where
showsPrec p = showsPrec1 p . getAction
Now we can write a test like this:
-- (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
testBindAssoc :: forall m . (Monad m, Arbitrary1 m, Show1 m, Eq1 m) => Proxy m -> Property
testBindAssoc _ =
forAllShrink (arbitrary :: Gen (Action m A)) shrink $ \m' ->
forAllShrink (arbitrary :: Gen (Fun A (Action m B))) shrink $ \f' ->
forAllShrink (arbitrary :: Gen (Fun B (Action m C))) shrink $ \g' ->
let m = getAction m'
f = getAction <$> apply f'
g = getAction <$> apply g'
k = (m >>= f) >>= g
l = m >>= (\x -> f x >>= g)
in counterexample (showsPrec1 0 k . showString " != " . showsPrec1 0 l $ "")
$ k `eq1` l
And let's write a broken Writer monad:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Writer
newtype MyMonad w a = MyMonad { runMyMonad :: Writer w a }
deriving (Functor, Applicative)
instance (Monoid w) => Monad (MyMonad w) where
return = pure
k >>= f = let (a, w) = runWriter . runMyMonad $ k
in MyMonad $ writer (a, w <> w) >>= (runMyMonad . f)
-- ^ broken here
getMyMonad :: MyMonad w a -> (a, w)
getMyMonad = runWriter . runMyMonad
instance (Eq w) => Eq1 (MyMonad w) where
eq1 k l = getMyMonad k == getMyMonad l
instance (Show w) => Show1 (MyMonad w) where
showsPrec1 p k = showsPrec p (getMyMonad k)
instance (Monoid w, Arbitrary w) => Arbitrary1 (MyMonad w) where
arbitrary1 = MyMonad . writer <$> arbitrary
shrink1 = map (MyMonad . writer) . shrink . getMyMonad
main :: IO ()
main = quickCheck (testBindAssoc (Proxy :: Proxy (MyMonad (Sum Int))))
Fails with:
*** Failed! Falsifiable (after 2 tests and 13 shrinks):
(1,Sum {getSum = 1})
{_->(1,Sum {getSum = 0})}
{_->(1,Sum {getSum = 0})}
(1,Sum {getSum = 4}) != (1,Sum {getSum = 2})
Any ideas for improvements?
Related
I'm learning Monad Transformers, and one of the exercises asks to implement the Monad instance for StateT.
I want to test that my implementation admits to the Monad laws using the validity package, which is like the checkers package.
Problem is, my Arbitrary instance doesn't compile. I saw this question, but it doesn't quite do what I want because the test basically duplicates the implementation and doesn't check the laws.
There's also this question, but it's unanswered, and I've already figured out how to test Monad Transformers not involving functions (like MaybeT).
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE InstanceSigs #-}
module Ch11.MonadT (StT (..)) where
import Control.Monad.Trans.State (StateT (..))
newtype StT s m a = StT (s -> m (a, s))
deriving
(Functor, Applicative)
via StateT s m
instance (Monad m) => Monad (StT s m) where
return :: a -> StT s m a
return = pure
(>>=) :: StT s m a -> (a -> StT s m b) -> StT s m b
StT x >>= f = StT $ \s -> do
(k, s') <- x s
let StT y = f k
y s'
(>>) :: StT s m a -> StT s m b -> StT s m b
(>>) = (*>)
My test:
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeApplications #-}
module Ch11.MonadTSpec (spec) where
import Ch11.MonadT (StT (..))
import Test.Hspec
import Test.QuickCheck
import Test.Validity.Monad
spec :: Spec
spec = do
monadSpecOnArbitrary #(StTArbit Int [] Int)
-- create wrapper to avoid orphan instance error
newtype StTArbit s m a = StTArbit (StT s m a)
deriving
(Functor, Applicative, Monad)
instance (Arbitrary s, Function s, Arbitrary1 m, Arbitrary a) => Arbitrary (StTArbit s m a) where
arbitrary = do
f <- arbitrary :: Fun s (m (a, s))
StTArbit . StT <$> f
Error:
• Couldn't match type: (a0, s0)
with: s -> m (a, s)
Expected: Gen (s -> m (a, s))
Actual: Gen (a0, s0)
• In the second argument of ‘(<$>)’, namely ‘f’
In a stmt of a 'do' block: StTArbit . StT <$> f
OP here, this is what I ended up doing.
-- https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/explicit_forall.html
{-# LANGUAGE ExplicitForAll #-}
-- https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_applications.html
{-# LANGUAGE TypeApplications #-}
module Ch11.MonadTSpec (spec) where
import Ch11.MonadT (StT (..), runStT)
import Data.Function as F
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
spec :: Spec
spec = do
describe "Monad (StT Int [])" $ do
describe "satisfies Monad laws" $ do
-- the types are in the same order as in `forall`
prop "right identity law" (prop_monadRightId #Int #Int #[])
prop "left identity law" (prop_monadLeftId #Int #Int #Int #[])
prop "associative law" (prop_monadAssoc #Int #Int #Int #Int #[])
{- HLINT ignore -}
{-
the types in `forall` are specified in the order of dependency.
since `m` needs `a` and `s`, those appear before `m` in the list.
-}
-- (x >>= return) == x
prop_monadRightId ::
forall a s m.
(Monad m, Eq (m (a, s)), Show (m (a, s))) =>
s ->
Fun s (m (a, s)) ->
Property
prop_monadRightId s f = ((===) `F.on` go) (m >>= return) m
where
m = StT $ applyFun f
go st = runStT st s
-- (return x >>= f) == (f x)
prop_monadLeftId ::
forall a b s m.
(Monad m, Eq (m (b, s)), Show (m (b, s))) =>
a ->
s ->
Fun (a, s) (m (b, s)) ->
Property
prop_monadLeftId a s f = ((===) `F.on` go) (return a >>= h) m
where
g = applyFun2 f
m = StT $ g a
h = StT . g
go st = runStT st s
-- ((x >>= f) >>= g) == (x >>= (\x' -> f x' >>= g))
prop_monadAssoc ::
forall a b c s m.
(Monad m, Eq (m (b, s)), Show (m (b, s)), Eq (m (c, s)), Show (m (c, s))) =>
s ->
Fun s (m (a, s)) ->
Fun (a, s) (m (b, s)) ->
Fun (b, s) (m (c, s)) ->
Property
prop_monadAssoc s h f g =
((===) `F.on` go)
((m >>= f') >>= g')
(m >>= (\x -> f' x >>= g'))
where
m = StT $ applyFun h
f' = StT . applyFun2 f
g' = StT . applyFun2 g
go st = runStT st s
I think you want pure, not (<$>). (But I haven't checked with my local compiler, so I'm not sure.) You probably also have to turn your Fun into an actual function.
arbitrary = do
f <- arbitrary
pure (StTArbit . StT . applyFun $ f)
I'd also point out that there's not much point to making a newtype here. I guess it avoids an orphan instance warning? But you've defined the type you're writing an instance for yourself, presumably even in the same package, so it seems pretty benign; if it's part of a separate cabal component that people can't depend on, like a test suite, even more so.
I am looking for practical strategies or tips for dealing with constraints in haskell, as illustrated by the case below.
I have a functor Choice and I want to transform an interpreter from Choice x functor to m x to an interpreter from Free Choice x to m x.
-- Choice : endofunctor
data Choice next = Choice next next deriving (Show)
instance Functor Choice where
fmap f (Choice a b) = Choice (f a) (f b)
-- I have a function from the functor to a monad m
inter1 :: Choice x -> IO x
inter1 (Choice a b) = do
x <- readLn :: IO Bool
return $ if x then a else b
-- universal property gives me a function from the free monad to m
go1 :: Free Choice x -> IO x
go1 = interpMonad inter1
where
type Free f a = FreeT f Identity a
data FreeF f r x = FreeF (f x) | Pure r deriving (Show)
newtype FreeT f m r = MkFreeT { runFreeT :: m (FreeF f r (FreeT f m r)) }
instance Show (m (FreeF f a (FreeT f m a))) => Show (FreeT f m a) where
showsPrec d (MkFreeT m) = showParen (d > 10) $
showString "FreeT " . showsPrec 11 m
instance (Functor f, Monad m) => Functor (FreeT f m) where
fmap (f::a -> b) (x::FreeT f m a) =
MkFreeT $ liftM f' (runFreeT x)
where f' :: FreeF f a (FreeT f m a) -> FreeF f b (FreeT f m b)
f' (FreeF (fx::f (FreeT f m a))) = FreeF $ fmap (fmap f) fx
f' (Pure r) = Pure $ f r
instance (Functor f, Monad m) => Applicative (FreeT f m) where
pure a = MkFreeT . return $ Pure a
(<*>) = ap
instance (Functor f, Monad m) => Monad (FreeT f m) where
return = MkFreeT . return . Pure
(MkFreeT m) >>= (f :: a -> FreeT f m b) = MkFreeT $ -- m (FreeF f b (FreeT f m b))
m >>= -- run the effect in the underlying monad !
\case FreeF fx -> return . FreeF . fmap (>>= f) $ fx -- continue to run effects
Pure r -> runFreeT (f r) -- apply the transformation
interpMonad :: (Functor f, Functor m, Monad m) =>
(forall x . f x -> m x) ->
forall x. Free f x -> m x
interpMonad interp (MkFreeT iFfxF) = (\case
Pure x -> return x
FreeF fxF -> let mmx = interp $ fmap (interpMonad interp) fxF
in join mmx) . runIdentity $ iFfxF
All is fine until I require Show x in my interpreter.
interp2 :: Show x => Choice x -> IO x
interp2 (Choice a b) = return a -- we follow left
go2 :: Show x => Free Choice x -> IO x
go2 = interpMonad interp2 -- FAILS
Then it can not find the show constraint to apply in interp2
I suspected the quantifiers were the problem, so I simplified to
lifting :: (forall x . x -> b) ->
(forall x. x -> b)
lifting = id
lifting2 :: (forall x . Show x => x -> b) ->
(forall x . Show x => x -> b)
lifting2 = id
somefunction :: Show x => x -> String
somefunction = lifting show -- FAILS
somefunction2 :: Show x => x -> String
somefunction2 = lifting2 show -- OK
This highlight the problem : Could not deduce (Show x1) arising from a use of ‘show’ from the context (Show x) we have two distinct type variable, and constraint do not flow from one to the other.
I could write some specialized function playing with the constraints as follows (does not work btw) but my question is what are the practical strategies for dealing with this ? (the equivalent of undefined, look at the type, go on...)
interpMonad2 :: (Functor f, Functor m, Monad m) =>
(forall x . ( Show (f x)) => f x -> m x) ->
forall x. ( Show (Free f x)) => Free f x -> m x
interpMonad2 interp (MkFreeT iFfxF) = (\case
Pure x -> return x
FreeF fxF -> let mmx = interp $ fmap (interpMonad interp) fxF
in join mmx) . runIdentity $ iFfxF
edit
based on the answer provided, here is the modification for the lifting function.
lifting :: forall b c. Proxy c
-> (forall x . c x => x -> b)
-> (forall x . c x => x -> b)
lifting _ = id
somefunction3 :: Show x => x -> String
somefunction3 = lifting (Proxy :: Proxy Show) show
I don't see your interpMonad function, so I will include one possible definition here:
interpMonad :: forall f m x . (Functor f, Monad m)
=> (forall y . f y -> m y) -> Free f x -> m x
interpMonad xx = go . runIdentity . runFreeT where
go (FreeF x) = xx x >>= go . runIdentity . runFreeT
go (Pure x) = return x
In order to also have a class constraint on the inner function, you simply add the constraint to the inner function. You also need the correct constraint on the type Free, and you need the extra Proxy to help the typechecker out a bit. Otherwise, the definition of the function is identical:
interpMonadC :: forall f m x c . (Functor f, Monad m, c (Free f x))
=> Proxy c
-> (forall y . c y => f y -> m y)
-> (Free f x -> m x)
interpMonadC _ xx = go . runIdentity . runFreeT where
go (FreeF x) = xx x >>= go . runIdentity . runFreeT
go (Pure x) = return x
And now quite simply:
>:t interpMonadC (Proxy :: Proxy Show) interp2
interpMonadC (Proxy :: Proxy Show) interp2
:: Show x => Free Choice x -> IO x
I needed a lens function that works like over, but with monadic operations:
overM :: (Monad m) => Lens s t a b -> (a -> m b) -> (s -> m t)
While this function is easy to define (it's actually just an identity modulo WrappedMonad), I wonder are such functions defined somewhere in lens?
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Control.Lens
overF :: (Functor f) => Lens s t a b -> (a -> f b) -> (s -> f t)
overF l = l
overM :: (Monad m) => Lens s t a b -> (a -> m b) -> (s -> m t)
overM l = (unwrapMonad .) . l . (WrapMonad .)
in Control.Lens.Traversal:
traverseOf :: Over p f s t a b -> p a (f b) -> s -> f t
traverseOf = id
mapMOf :: Profunctor p =>
Over p (WrappedMonad m) s t a b -> p a (m b) -> s -> m t
mapMOf l cmd = unwrapMonad #. l (WrapMonad #. cmd)
Example:
Prelude Control.Lens> traverseOf _1 (Just . (+2)) (2,2)
Just (4,2)
Prelude Control.Lens> mapMOf _1 (Just . (+2)) (2,2)
Just (4,2)
I know with the data constructor and the run*** function,
I can lift any function to a specific MonadTrans instance.
Like this,
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Control.Monad
liftF :: (Monad m) => (a -> b) -> MaybeT m a -> MaybeT m b
liftF f x = MaybeT $ do
inner <- runMaybeT x
return $ liftM f inner
But how can I generalize this liftF to
liftF :: (MonadTrans t, Monad m) => (a -> b) -> t m a -> t m b
As #thoferon mentioned, you can just use liftM:
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Control.Monad (liftM)
liftF :: (Monad m) => (a -> b) -> MaybeT m a -> MaybeT m b
liftF f m = liftM f m
liftF' :: (MonadTrans t, Monad m, Monad (t m)) => (a -> b) -> t m a -> t m b
liftF' f m = liftM f m
(I had to add an additional Monad constraint to liftF').
But why would you do this? Check out the source code for MaybeT -- there's already a Monad instance:
instance (Monad m) => Monad (MaybeT m) where
fail _ = MaybeT (return Nothing)
return = lift . return
x >>= f = MaybeT $ do
v <- runMaybeT x
case v of
Nothing -> return Nothing
Just y -> runMaybeT (f y)
And actually, as liftM is the same as Functor's fmap:
instance (Functor m) => Functor (MaybeT m) where
fmap f = mapMaybeT (fmap (fmap f))
You can find similar instances for all the transformers.
Is this what you are asking? Can you provide some more concrete examples that show what you're trying to do and why, and in what way the existing Functor and Monad instances fail to meet your needs?
I want mapM over something that is traversable while passing an accumulator. I came up with:
import Control.Applicative
import Data.Traversable
import Control.Monad.State
mapAccumM :: (Applicative m, Traversable t, MonadState s m)
=> (s -> a -> m (s, b)) -> s -> t a -> m (t b)
mapAccumM f acc0 xs = put acc0 >> traverse g xs
where
g x = do
oldAcc <- get
(newAcc, y) <- f oldAcc x
put newAcc
return y
How can this be done without State monad?
roconnor answered this for me on #haskell
this solves my problem but notice that accumulator is returned in the second element of the tuple instead of the first
mapAccumM :: (Monad m, Functor m, Traversable t) => (a -> b -> m (c, a)) -> a -> t b -> m (t c)
mapAccumM f = flip (evalStateT . (Data.Traversable.traverse (StateT . (flip f))))
or to also return the accumulator:
mapAccumM' :: (Monad m, Functor m, Traversable t) => (a -> b -> m (c, a)) -> a -> t b -> m (t c, a)
mapAccumM' f = flip (runStateT . (Data.Traversable.traverse (StateT . (flip f))))