File: Monad.hs

package info (click to toggle)
haskell-hedgehog-classes 0.2.5.4-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 504 kB
  • sloc: haskell: 6,010; makefile: 5
file content (118 lines) | stat: -rw-r--r-- 2,695 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{-# language
        DerivingStrategies
      , GeneralizedNewtypeDeriving
  #-}

module Spec.Monad
  ( testMonad
  , testMonadIO
  , testMonadPlus
  , testMonadZip
  ) where

import Control.Applicative (Alternative(..), liftA2)
import Control.Monad.IO.Class (MonadIO(..))

import Data.Functor.Identity (Identity(..))

import Hedgehog
import Hedgehog.Classes

import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range

import System.IO.Unsafe (unsafePerformIO)

import Prelude hiding (either)

testMonad :: [(String, [Laws])]
testMonad =
  [ ("[]", lawsList)
  , ("Either e", lawsEither)
  , ("Identity", lawsIdentity)
  , ("IO", lawsIO)
  , ("Maybe", lawsMaybe)
  ]

{-
testMonadFix :: [(String, [Laws])]
testMonadFix =
  [ ("[]", fixLawsList)
  , ("Either e", fixLawsEither)
  , ("Identity", fixLawsIdentity)
  , ("IO", fixLawsIO)
  , ("Maybe", fixLawsMaybe)
  ]
-}

testMonadIO :: [(String, [Laws])]
testMonadIO =
  [ ("IO", ioLawsIO)
  ]

testMonadPlus :: [(String, [Laws])]
testMonadPlus =
  [ ("[]", plusLawsList)
  , ("Maybe", plusLawsMaybe)
  ]

testMonadZip :: [(String, [Laws])]
testMonadZip =
  [ ("[]", zipLawsList)
  , ("Identity", zipLawsIdentity)
  , ("Maybe", zipLawsMaybe)
  ]

lawsEither :: [Laws]
lawsEither = [monadLaws eitherInteger]

eitherInteger :: MonadGen m => m a -> m (Either Integer a)
eitherInteger = either (Gen.integral (Range.linear 0 20))

either :: MonadGen m => m e -> m a -> m (Either e a)
either genE genA =
  Gen.sized $ \n ->
    Gen.frequency [
        (2, Left <$> genE)
      , (1 + fromIntegral n, Right <$> genA)
      ]

lawsIdentity, zipLawsIdentity :: [Laws]
lawsIdentity = [monadLaws identity]
zipLawsIdentity = [monadZipLaws identity]

identity :: MonadGen m => m a -> m (Identity a)
identity = fmap Identity

lawsList, plusLawsList, zipLawsList :: [Laws]
lawsList = [monadLaws list]
plusLawsList = [monadPlusLaws list]
zipLawsList = [monadZipLaws list]

list :: MonadGen m => m a -> m [a]
list = Gen.list $ Range.linear 0 6

lawsMaybe, plusLawsMaybe, zipLawsMaybe :: [Laws]
lawsMaybe = [monadLaws Gen.maybe]
plusLawsMaybe = [monadPlusLaws Gen.maybe]
zipLawsMaybe = [monadZipLaws Gen.maybe]

lawsIO, ioLawsIO :: [Laws]
lawsIO = [monadLaws io]
ioLawsIO = [monadIOLaws io]

newtype TestIO a = TestIO (IO a)
  deriving newtype (Functor, Applicative, Monad, Alternative)

-- | Unsafe!
instance Eq a => Eq (TestIO a) where
  TestIO a == TestIO b = unsafePerformIO $ liftA2 (==) a b
  {-# noinline (==) #-}
-- | Unsafe!
instance Show a => Show (TestIO a) where
  showsPrec d (TestIO a) = unsafePerformIO $ fmap (showsPrec d) a
instance MonadIO TestIO where
  liftIO = TestIO

io :: MonadGen m => m a -> m (TestIO a)
io = fmap pure