{-# LANGUAGE TypeFamilies #-}
-- |
-- Module : Data.Adaptive.Maybe
-- Copyright : (c) Don Stewart 2009
-- License : BSD-style
-- Maintainer : dons@galois.com
-- Stability : experimental
--
-- Self optimzing sum types.
--
-- This library statically adapts the polymorphic container
-- representation of Maybe to specific, more efficient representations,
-- when instantiated with particular monomorphic types. It does this via
-- an associated more efficient data type for each pair of elements you
-- wish to store in your container.
--
-- That is, instead of representing 'Maybe Int' as:
--
-- > Just
-- > |
-- > I# 3#
--
-- A self-optimizing pair will unpack the constructors, yielding this
-- data representation:
--
-- > JustInt 3#
--
-- Saving an indirection. The resulting structure should be both more
-- time and space efficient than the generic polymorphic container it is
-- derived from.
--
-- Self adaptive polymorphic containers are able to unpack their
-- components, something not possible with, for example, strict
-- polymorphic containers.
--
module Data.Adaptive.Maybe where
import Prelude hiding (Maybe(..), maybe)
import Data.Word
import Data.Int
class AdaptMaybe a where
data Maybe a
-- construction
just :: a -> Maybe a
{-# INLINE just #-}
nothing :: Maybe a
{-# INLINE nothing #-}
-- | The 'isJust' function returns 'True' iff its argument is of the
-- form @Just _@.
isJust :: Maybe a -> Bool
{-# INLINE isJust #-}
-- elimination
maybe :: b -> (a -> b) -> Maybe a -> b
{-# INLINE maybe #-}
------------------------------------------------------------------------
-- | The 'isNothing' function returns 'True' iff its argument is 'Nothing'.
isNothing :: AdaptMaybe a => Maybe a -> Bool
isNothing = not . isJust
{-# INLINE isNothing #-}
-- | The 'fromJust' function extracts the element out of a 'Just' and
-- throws an error if its argument is 'Nothing'.
fromJust :: AdaptMaybe a => Maybe a -> a
fromJust = maybe (error "Data.Adaptive.Maybe.fromJust: Nothing") id
{-# INLINE fromJust #-}
-- | The 'fromMaybe' function takes a default value and and 'Maybe'
-- value. If the 'Maybe' is 'Nothing', it returns the default values;
-- otherwise, it returns the value contained in the 'Maybe'.
fromMaybe :: AdaptMaybe a => a -> Maybe a -> a
fromMaybe d = maybe d id
{-# INLINE fromMaybe #-}
-- | The 'maybeToList' function returns an empty list when given
-- 'Nothing' or a singleton list when not given 'Nothing'.
maybeToList :: AdaptMaybe a => Maybe a -> [a]
maybeToList = maybe [] (:[])
{-# INLINE maybeToList #-}
-- | The 'listToMaybe' function returns 'Nothing' on an empty list
-- or @'Just' a@ where @a@ is the first element of the list.
listToMaybe :: AdaptMaybe a => [a] -> Maybe a
listToMaybe [] = nothing
listToMaybe (a:_) = just a
{-# INLINE listToMaybe #-}
-- | The 'catMaybes' function takes a list of 'Maybe's and returns
-- a list of all the 'Just' values.
catMaybes :: AdaptMaybe a => [Maybe a] -> [a]
catMaybes ls = [ fromJust x | x <- ls, isJust x ]
-- | The 'mapMaybe' function is a version of 'map' which can throw
-- out elements. In particular, the functional argument returns
-- something of type @'Maybe' b@. If this is 'Nothing', no element
-- is added on to the result list. If it just @'Just' b@, then @b@ is
-- included in the result list.
mapMaybe :: AdaptMaybe b => (a -> Maybe b) -> [a] -> [b]
mapMaybe _ [] = []
mapMaybe f (x:xs) = maybe rs (:rs) (f x)
where
rs = mapMaybe f xs
------------------------------------------------------------------------
-- Generated by scripts/derive-maybe.hs
-- Instances
--
instance AdaptMaybe Int where
data Maybe Int = NothingInt | JustInt {-# UNPACK #-}!Int
just = JustInt
nothing = NothingInt
isJust (JustInt _) = True
isJust _ = False
maybe n _ NothingInt = n
maybe _ f (JustInt x) = f x
instance AdaptMaybe Integer where
data Maybe Integer = NothingInteger | JustInteger {-# UNPACK #-}!Integer
just = JustInteger
nothing = NothingInteger
isJust (JustInteger _) = True
isJust _ = False
maybe n _ NothingInteger = n
maybe _ f (JustInteger x) = f x
instance AdaptMaybe Int8 where
data Maybe Int8 = NothingInt8 | JustInt8 {-# UNPACK #-}!Int8
just = JustInt8
nothing = NothingInt8
isJust (JustInt8 _) = True
isJust _ = False
maybe n _ NothingInt8 = n
maybe _ f (JustInt8 x) = f x
instance AdaptMaybe Int16 where
data Maybe Int16 = NothingInt16 | JustInt16 {-# UNPACK #-}!Int16
just = JustInt16
nothing = NothingInt16
isJust (JustInt16 _) = True
isJust _ = False
maybe n _ NothingInt16 = n
maybe _ f (JustInt16 x) = f x
instance AdaptMaybe Int32 where
data Maybe Int32 = NothingInt32 | JustInt32 {-# UNPACK #-}!Int32
just = JustInt32
nothing = NothingInt32
isJust (JustInt32 _) = True
isJust _ = False
maybe n _ NothingInt32 = n
maybe _ f (JustInt32 x) = f x
instance AdaptMaybe Int64 where
data Maybe Int64 = NothingInt64 | JustInt64 {-# UNPACK #-}!Int64
just = JustInt64
nothing = NothingInt64
isJust (JustInt64 _) = True
isJust _ = False
maybe n _ NothingInt64 = n
maybe _ f (JustInt64 x) = f x
instance AdaptMaybe Word where
data Maybe Word = NothingWord | JustWord {-# UNPACK #-}!Word
just = JustWord
nothing = NothingWord
isJust (JustWord _) = True
isJust _ = False
maybe n _ NothingWord = n
maybe _ f (JustWord x) = f x
instance AdaptMaybe Word8 where
data Maybe Word8 = NothingWord8 | JustWord8 {-# UNPACK #-}!Word8
just = JustWord8
nothing = NothingWord8
isJust (JustWord8 _) = True
isJust _ = False
maybe n _ NothingWord8 = n
maybe _ f (JustWord8 x) = f x
instance AdaptMaybe Word16 where
data Maybe Word16 = NothingWord16 | JustWord16 {-# UNPACK #-}!Word16
just = JustWord16
nothing = NothingWord16
isJust (JustWord16 _) = True
isJust _ = False
maybe n _ NothingWord16 = n
maybe _ f (JustWord16 x) = f x
instance AdaptMaybe Word32 where
data Maybe Word32 = NothingWord32 | JustWord32 {-# UNPACK #-}!Word32
just = JustWord32
nothing = NothingWord32
isJust (JustWord32 _) = True
isJust _ = False
maybe n _ NothingWord32 = n
maybe _ f (JustWord32 x) = f x
instance AdaptMaybe Word64 where
data Maybe Word64 = NothingWord64 | JustWord64 {-# UNPACK #-}!Word64
just = JustWord64
nothing = NothingWord64
isJust (JustWord64 _) = True
isJust _ = False
maybe n _ NothingWord64 = n
maybe _ f (JustWord64 x) = f x
instance AdaptMaybe Double where
data Maybe Double = NothingDouble | JustDouble {-# UNPACK #-}!Double
just = JustDouble
nothing = NothingDouble
isJust (JustDouble _) = True
isJust _ = False
maybe n _ NothingDouble = n
maybe _ f (JustDouble x) = f x
instance AdaptMaybe Float where
data Maybe Float = NothingFloat | JustFloat {-# UNPACK #-}!Float
just = JustFloat
nothing = NothingFloat
isJust (JustFloat _) = True
isJust _ = False
maybe n _ NothingFloat = n
maybe _ f (JustFloat x) = f x
instance AdaptMaybe Char where
data Maybe Char = NothingChar | JustChar {-# UNPACK #-}!Char
just = JustChar
nothing = NothingChar
isJust (JustChar _) = True
isJust _ = False
maybe n _ NothingChar = n
maybe _ f (JustChar x) = f x