Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion strict-base-types/src/Data/Maybe/Strict.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
-- corresponding variants of the functions from "Data.Maybe".
--
-- Note that in contrast to the standard lazy 'L.Maybe' type, the strict
-- 'Maybe' type is not an applicative functor, and therefore also not a monad.
-- 'Maybe' type does not have lawful 'Functor', 'Applicative', or 'Monad' instances.
-- However, we provide instances for these type classes (and related others)
-- since they are only partial due to the below example.
--
-- The problem is the /homomorphism/ law, which states that
--
-- @'pure' f '<*>' 'pure' x = 'pure' (f x) -- must hold for all f@
Expand All @@ -28,6 +31,8 @@
-- 'Maybe', as this instance does not satisfy @pure f \<*\> pure _|_ = pure (f
-- _|_)@ for @f = const@.
--
-- This exception to the law is acceptable because we would expect a strict type to diverge on _|_ .
--
-----------------------------------------------------------------------------

module Data.Maybe.Strict (
Expand Down
25 changes: 21 additions & 4 deletions strict/src/Data/Strict/Either.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
-- The strict variant of the standard Haskell 'L.Either' type and the
-- corresponding variants of the functions from "Data.Either".
--
-- Note that the strict 'Either' type is not an applicative functor, and
-- Note that the strict 'Either' type is not technically an applicative functor, and
-- therefore also no monad. The reasons are the same as the ones for the
-- strict @Maybe@ type, which are explained in "Data.Maybe.Strict".
-- strict @Maybe@ type, which are explained in "Data.Maybe.Strict", but we define
-- instances for the same reasons listed as well.
--
-----------------------------------------------------------------------------

Expand All @@ -38,8 +39,9 @@ module Data.Strict.Either (

-- import parts explicitly, helps with compatibility
import Prelude ( Functor (..), Eq (..), Ord (..), Show (..), Read (..), Bool (..), (.), ($)
, error, Ordering (..), showParen, showString, lex, return, readParen)
import Control.Applicative (pure, (<$>))
, error, Ordering (..), showParen, showString, lex, readParen)
import Control.Applicative (Applicative (..), (<$>))
import Control.Monad (Monad (..))
import Data.Semigroup (Semigroup (..))
import Data.Foldable (Foldable (..))
import Data.Traversable (Traversable (..))
Expand Down Expand Up @@ -162,6 +164,21 @@ instance Semigroup (Either a b) where
Left _ <> b = b
a <> _ = a

-- | Unlawful when given `Right _|_`, due to the homomorphism law
instance Applicative (Either e) where
pure = Right

Right f <*> m = fmap f m
Left l <*> _m = Left l

instance Monad (Either e) where
(Right x) >>= k = k x
Left e >>= _ = Left e

(>>) = (*>)

return = pure

-- deepseq
instance (NFData a, NFData b) => NFData (Either a b) where
rnf = rnf . toLazy
Expand Down
43 changes: 40 additions & 3 deletions strict/src/Data/Strict/Maybe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
-- corresponding variants of the functions from "Data.Maybe".
--
-- Note that in contrast to the standard lazy 'L.Maybe' type, the strict
-- 'Maybe' type is not an applicative functor, and therefore also not a monad.
-- 'Maybe' type does not have lawful 'Functor', 'Applicative', or 'Monad' instances.
-- However, we provide instances for these type classes (and related others)
-- since they are only partial due to the below example.
--
-- The problem is the /homomorphism/ law, which states that
--
-- @'pure' f '<*>' 'pure' x = 'pure' (f x) -- must hold for all f@
Expand All @@ -31,6 +34,8 @@
-- 'Maybe', as this instance does not satisfy @pure f \<*\> pure _|_ = pure (f
-- _|_)@ for @f = const@.
--
-- This exception to the law is acceptable because we would expect a strict type to diverge on _|_ .
--
-----------------------------------------------------------------------------

module Data.Strict.Maybe (
Expand All @@ -48,8 +53,9 @@ module Data.Strict.Maybe (

-- import parts explicitly, helps with compatibility
import Prelude (Functor (..), Eq (..), Ord (..), Show (..), Read (..), Bool (..), (.)
,error, Ordering (..), ($), showString, showParen, return, lex, readParen)
import Control.Applicative (pure, (<$>))
,error, Ordering (..), ($), showString, showParen, lex, readParen)
import Control.Applicative (Applicative (..), Alternative (..), (<$>))
import Control.Monad (Monad (..), MonadPlus (..))
import Data.Monoid (Monoid (..))
import Data.Semigroup (Semigroup (..))
import Data.Foldable (Foldable (..))
Expand Down Expand Up @@ -181,6 +187,37 @@ instance Traversable Maybe where
traverse _ Nothing = pure Nothing
traverse f (Just x) = Just <$> f x

-- | Unlawful when given `Just _|_`, due to the homomorphism law
instance Applicative Maybe where
-- thanks to https://hackage.haskell.org/package/base-4.19.1.0/docs/src/GHC.Base.html#line-1161
pure = Just

Just f <*> m = fmap f m
Nothing <*> _m = Nothing

liftA2 f (Just x) (Just y) = Just (f x y)
liftA2 _ _ _ = Nothing

Just _m1 *> m2 = m2
Nothing *> _m2 = Nothing

instance Monad Maybe where
-- thanks to https://hackage.haskell.org/package/base-4.19.1.0/docs/src/GHC.Base.html#line-1161
(Just x) >>= k = k x
Nothing >>= _ = Nothing

(>>) = (*>)

return = pure

instance Alternative Maybe where
-- thanks to https://hackage.haskell.org/package/base-4.19.1.0/docs/src/GHC.Base.html#line-1161
empty = Nothing
Nothing <|> r = r
l <|> _ = l

instance MonadPlus Maybe

-- deepseq
instance NFData a => NFData (Maybe a) where
rnf = rnf . toLazy
Expand Down
15 changes: 13 additions & 2 deletions strict/src/Data/Strict/Tuple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ module Data.Strict.Tuple (

-- import parts explicitly, helps with compatibility
import Prelude (Functor (..), Eq (..), Ord (..), Show (..), Read (..), (.), Bounded, map, ($)
, (&&), showParen, showString, readParen, lex, return)
import Control.Applicative ((<$>), (<*>))
, (&&), showParen, showString, readParen, lex)
import Control.Applicative (Applicative (..), (<$>), (<*>))
import Control.Monad (Monad (..))
import Data.Monoid (Monoid (..))
import Data.Semigroup (Semigroup (..))
import Data.Foldable (Foldable (..))
Expand Down Expand Up @@ -170,6 +171,16 @@ instance (Monoid a, Monoid b) => Monoid (Pair a b) where
mempty = mempty :!: mempty
(x1 :!: y1) `mappend` (x2 :!: y2) = (x1 `mappend` x2) :!: (y1 `mappend` y2)

instance Monoid l => Applicative (Pair l) where
pure = (mempty :!:)
(u :!: f) <*> (v :!: x) = (u <> v) :!: f x
liftA2 f (u :!: x) (v :!: y) = (u <> v) :!: f x y

instance Monoid l => Monad (Pair l) where
(u :!: a) >>= k = case k a of (v :!: b) -> (u <> v) :!: b

return = pure

-- deepseq
instance (NFData a, NFData b) => NFData (Pair a b) where
rnf = rnf . toLazy
Expand Down