packages feed

logict-sequence-0.2.0.2: src/Control/Monad/Logic/Sequence/Internal.hs

{-# LANGUAGE CPP #-}
#include "logict-sequence.h"
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
#if __GLASGOW_HASKELL__ < 710
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
#endif
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

#ifdef USE_PATTERN_SYNONYMS
{-# LANGUAGE PatternSynonyms #-}
#endif

{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_HADDOCK not-home #-}
#if __GLASGOW_HASKELL__ >= 902
-- We need this for now to work around
-- https://gitlab.haskell.org/ghc/ghc/-/issues/22549 which otherwise causes
-- infinite loops in several instances. It's definitely needed for GHC 9.4; we
-- do it for 9.2 as well just in case, as others have gotten loops with
-- -fdicts-strict with that version.
{-# OPTIONS_GHC -fno-dicts-strict #-}
#endif

{- OPTIONS_GHC -ddump-simpl -dsuppress-coercions #-}

-- | Based on the LogicT improvements in the paper, Reflection without
-- Remorse. Code is based on the code provided in:
-- https://github.com/atzeus/reflectionwithoutremorse
--
-- Note: that code is provided under an MIT license, so we use that as
-- well.
module Control.Monad.Logic.Sequence.Internal
(
#ifdef USE_PATTERN_SYNONYMS
    SeqT(MkSeqT, getSeqT, ..)
#else
    SeqT(..)
#endif
  , Seq
#ifdef USE_PATTERN_SYNONYMS
  , pattern MkSeq
  , getSeq
#endif
  , ViewT(..)
  , View
  , viewT
  , view
  , toViewT
  , toView
  , fromViewT
  , fromView
  , observeAllT
  , observeAll
  , observeManyT
  , observeMany
  , observeT
  , observe
  , fromSeqT
  , hoistPre
  , hoistPost
  , hoistPreUnexposed
  , hoistPostUnexposed
  , toLogicT
  , fromLogicT
  , cons
  , consM
  , choose
  , chooseM
)
where

import Control.Applicative
import Control.Monad hiding (liftM)
#if !MIN_VERSION_base(4,8,0)
import qualified Control.Monad as Monad
#endif
import qualified Control.Monad.Fail as Fail
import Control.Monad.Identity (Identity(..))
import Control.Monad.Trans (MonadTrans(..))
import Control.Monad.Logic.Class
import qualified Control.Monad.Logic as L
import Control.Monad.IO.Class
import Control.Monad.Reader.Class (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Error.Class (MonadError (..))
import Control.Monad.Morph (MFunctor (..))
import qualified Data.SequenceClass as S
import Control.Monad.Logic.Sequence.Internal.Queue (Queue)
#if MIN_VERSION_base(4,8,0)
import Control.Monad.Zip (MonadZip (..))
#endif
import qualified Text.Read as TR
import Data.Function (on)
#if MIN_VERSION_base(4,9,0)
import Data.Functor.Classes
#endif

#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (Monoid(..))
#endif

#if MIN_VERSION_base(4,9,0)
import Data.Semigroup (Semigroup(..))
#endif

import qualified Data.Foldable as F
import qualified Data.Traversable as T
import GHC.Generics (Generic)
import Data.Coerce (coerce)

-- | A view of the front end of a 'SeqT'.
data ViewT m a = Empty | a :< SeqT m a
  deriving Generic
infixl 5 :<

type View = ViewT Identity

-- | A catamorphism for 'ViewT's
viewT :: b -> (a -> SeqT m a -> b) -> ViewT m a -> b
viewT n _ Empty = n
viewT _ c (a :< s) = c a s
{-# INLINE viewT #-}

-- | A catamorphism for 'View's. Note that this is just a type-restricted version
-- of 'viewT'.
view :: b -> (a -> Seq a -> b) -> View a -> b
view = viewT
{-# INLINE view #-}

deriving instance (Show a, Show (SeqT m a)) => Show (ViewT m a)
deriving instance (Read a, Read (SeqT m a)) => Read (ViewT m a)
deriving instance (Eq a, Eq (SeqT m a)) => Eq (ViewT m a)
deriving instance (Ord a, Ord (SeqT m a)) => Ord (ViewT m a)
deriving instance Monad m => Functor (ViewT m)
deriving instance (Monad m, F.Foldable m) => F.Foldable (ViewT m)
instance (Monad m, T.Traversable m) => T.Traversable (ViewT m) where
  traverse _ Empty = pure Empty
  traverse f (x :< xs) =
    liftA2 (\y ys -> y :< fromViewT ys) (f x) (T.traverse (T.traverse f) . toViewT $ xs)
--  The derived instance would use
--
--    traverse f (x :< xs) = liftA2 (:<) (f x) (traverse f xs)
--
--  Inlining the inner `traverse` reveals an application of `fmap` which
--  we fuse with `liftA2`, in case `fmap` isn't free.

#if MIN_VERSION_base(4,9,0)
instance (Eq1 m, Monad m) => Eq1 (ViewT m) where
  liftEq _ Empty Empty = True
  liftEq eq (a :< s) (b :< t) = eq a b && liftEq eq s t
  liftEq _ _ _ = False

instance (Ord1 m, Monad m) => Ord1 (ViewT m) where
  liftCompare _ Empty Empty = EQ
  liftCompare _ Empty (_ :< _) = LT
  liftCompare cmp (a :< s) (b :< t) = cmp a b `mappend` liftCompare cmp s t
  liftCompare _ (_ :< _) Empty = GT

instance (Show1 m, Monad m) => Show1 (ViewT m) where
  liftShowsPrec sp sl d val = case val of
    Empty -> ("Empty" ++)
    a :< s -> showParen (d > 5) $
      sp 6 a .
      showString " :< " .
      liftShowsPrec sp sl 6 s
#endif

-- | An asymptotically efficient logic monad transformer. It is generally best to
-- think of this as being defined
--
-- @
-- newtype SeqT m a = 'MkSeqT' { 'getSeqT' :: m ('ViewT' m a) }
-- @
--
-- Using the 'MkSeqT' pattern synonym with 'getSeqT', you can (almost) pretend
-- it's really defined this way! However, the real implementation is different,
-- so as to be more efficient in the face of deeply left-associated `<|>` or
-- `mplus` applications.
newtype SeqT m a = SeqT (Queue (m (ViewT m a)))

#ifdef USE_PATTERN_SYNONYMS
pattern MkSeqT :: Monad m => m (ViewT m a) -> SeqT m a
pattern MkSeqT{getSeqT} <- (toViewT -> getSeqT)
  where
    MkSeqT = fromViewT
{-# COMPLETE MkSeqT #-}

pattern MkSeq :: View a -> Seq a
pattern MkSeq{getSeq} = MkSeqT (Identity getSeq)
{-# COMPLETE MkSeq #-}
#endif

-- | A specialization of 'SeqT' to the 'Identity' monad. You can
-- imagine that this is defined
--
-- @
-- newtype Seq a = MkSeq { getSeq :: ViewT Identity a }
-- @
--
-- Using the 'MkSeq' pattern synonym with 'getSeq', you can pretend it's
-- really defined this way! However, the real implementation is different,
-- so as to be more efficient in the face of deeply left-associated `<|>`
-- or `mplus` applications.
type Seq = SeqT Identity

fromViewT :: m (ViewT m a) -> SeqT m a
fromViewT = SeqT . S.singleton
{-# INLINABLE [1] fromViewT #-}

fromView :: forall a. View a -> Seq a
fromView = coerce (fromViewT :: Identity (View a) -> Seq a)
{-# INLINE fromView #-}

toViewT :: Monad m => SeqT m a -> m (ViewT m a)
toViewT (SeqT s) = case S.viewl s of
  S.EmptyL -> return Empty
  h S.:< t -> h >>= \x -> case x of
    Empty -> toViewT (SeqT t)
    hi :< SeqT ti -> return (hi :< SeqT (ti S.>< t))
{-# INLINEABLE [1] toViewT #-}

toView :: forall a. Seq a -> View a
toView = coerce (toViewT :: SeqT Identity a -> Identity (ViewT Identity a))
{-# INLINABLE toView #-}

-- For now, we don't assume the monad identity law holds for the underlying
-- monad. We may re-evaluate that later, but it's a bit tricky to document the
-- detailed strictness requirements properly.
--
-- We do, however, assume that `pure /= _|_`, or that `>>=` doesn't `seq` on
-- its second argument, and that we can therefore eta-reduce `\x -> pure x` to
-- just `pure`. It seems quite safe to assume that at least one of these is
-- true, since in real code they're virtually always *both* true.
{-# RULES
"toViewT . fromViewT" forall m. toViewT (fromViewT m) = m >>= return
 #-}

{-
Theorem: toViewT . fromViewT = id

Proof:

toViewT (fromViewT m)
=
toViewT (SeqT (singleton m))
=
case viewl (singleton m) of
    h S.:< t -> h >>= \x -> case x of
      Empty -> toViewT (SeqT t)
      hi :< SeqT ti -> return (hi :< SeqT (ti S.>< t))
=
m >>= \x -> case x of
  Empty -> toViewT (SeqT S.empty)
  hi :< SeqT ti -> return (hi :< SeqT ti)
=
m >>= \x -> case x of
  Empty -> return Empty
  hi :< SeqT ti -> return (hi :< SeqT ti)
= m >>= \x -> return x
= m -- assuming the appropriate identity law holds for the underlying monad.
-}

instance (Show (m (ViewT m a)), Monad m) => Show (SeqT m a) where
  showsPrec d s = showParen (d > app_prec) $
      showString "MkSeqT " . showsPrec (app_prec + 1) (toViewT s)
    where app_prec = 10

instance Read (m (ViewT m a)) => Read (SeqT m a) where
  readPrec = TR.parens $ TR.prec app_prec $ do
      TR.Ident "MkSeqT" <- TR.lexP
      m <- TR.step TR.readPrec
      return (fromViewT m)
    where app_prec = 10
  readListPrec = TR.readListPrecDefault

instance (Eq a, Eq (m (ViewT m a)), Monad m) => Eq (SeqT m a) where
  (==) = (==) `on` toViewT
instance (Ord a, Ord (m (ViewT m a)), Monad m) => Ord (SeqT m a) where
  compare = compare `on` toViewT


#if MIN_VERSION_base(4,9,0)
instance (Eq1 m, Monad m) => Eq1 (SeqT m) where
  liftEq eq s t = liftEq (liftEq eq) (toViewT s) (toViewT t)

instance (Ord1 m, Monad m) => Ord1 (SeqT m) where
  liftCompare eq s t = liftCompare (liftCompare eq) (toViewT s) (toViewT t)

instance (Show1 m, Monad m) => Show1 (SeqT m) where
  liftShowsPrec sp sl d s = showParen (d > app_prec) $
      showString "MkSeqT " . liftShowsPrec (liftShowsPrec sp sl) (liftShowList sp sl) (app_prec + 1) (toViewT s)
    where app_prec = 10
#endif

single :: Monad m => a -> m (ViewT m a)
single a = return (a :< mzero)
{-# INLINE single #-}

instance Monad m => Functor (SeqT m) where
  {-# INLINEABLE fmap #-}
  fmap f (SeqT q) = SeqT $ fmap (myliftM (fmap f)) q
  {-# INLINABLE (<$) #-}
  x <$ SeqT q = SeqT $ fmap (myliftM (x <$)) q

instance Monad m => Applicative (SeqT m) where
  {-# INLINE pure #-}
  {-# INLINABLE (<*>) #-}
  pure = fromViewT . single

#if MIN_VERSION_base(4,8,0)
  fs <*> xs = fs >>= \f -> f <$> xs
#else
  (<*>) = ap
#endif

  {-# INLINABLE (*>) #-}
  (toViewT -> m) *> n = fromViewT $ thenViewT m n

#if MIN_VERSION_base(4,10,0)
  liftA2 f xs ys = xs >>= \x -> f x <$> ys
  {-# INLINABLE liftA2 #-}
#endif

thenViewT :: Monad m => m (ViewT m a) -> SeqT m b -> m (ViewT m b)
thenViewT m n = m >>= \x -> case x of
  Empty -> return Empty
  _ :< t -> toViewT n `altViewT` (t *> n)
{-# INLINABLE thenViewT #-}

instance Monad m => Alternative (SeqT m) where
  {-# INLINE empty #-}
  {-# INLINEABLE (<|>) #-}
  empty = SeqT S.empty
  SeqT m <|> SeqT n = SeqT (m S.>< n)

-- |
-- @
-- altViewT s t = toViewT (fromViewT s <|> t)
-- @
--
-- Question: is this actually good for optimization?
altViewT :: Monad m => m (ViewT m a) -> SeqT m a -> m (ViewT m a)
altViewT m n = m >>= \x -> case x of
  Empty -> toViewT n
  h :< t -> return (h :< (t <|> n))
{-# INLINABLE altViewT #-}

-- | @cons a s = pure a <|> s@
cons :: Monad m => a -> SeqT m a -> SeqT m a
cons a s = fromViewT (return (a :< s))
{-# INLINE cons #-}

-- | @consM m s = lift m <|> s@
consM :: Monad m => m a -> SeqT m a -> SeqT m a
consM m s = fromViewT (myliftM (:< s) m)
{-# INLINE consM #-}

instance Monad m => Monad (SeqT m) where
  {-# INLINE return #-}
  {-# INLINABLE (>>=) #-}
  return = pure
  (toViewT -> m) >>= f = fromViewT $ bindViewT m f
  (>>) = (*>)

#if !MIN_VERSION_base(4,13,0)
  {-# INLINEABLE fail #-}
  fail = Fail.fail
#endif

bindViewT :: Monad m => m (ViewT m a) -> (a -> SeqT m b) -> m (ViewT m b)
bindViewT m f = m >>= \x -> case x of
  Empty -> return Empty
  h :< t -> toViewT (f h) `altViewT` (t >>= f)
{-# INLINABLE bindViewT #-}

instance Monad m => Fail.MonadFail (SeqT m) where
  {-# INLINEABLE fail #-}
  fail _ = SeqT S.empty

instance Monad m => MonadPlus (SeqT m) where
  {-# INLINE mzero #-}
  {-# INLINE mplus #-}
  mzero = Control.Applicative.empty
  mplus = (<|>)

#if MIN_VERSION_base(4,9,0)
instance Monad m => Semigroup (SeqT m a) where
  {-# INLINE (<>) #-}
  {-# INLINE sconcat #-}
  (<>) = mplus
  sconcat = F.asum
#endif

instance Monad m => Monoid (SeqT m a) where
  {-# INLINE mempty #-}
  {-# INLINE mconcat #-}
  mempty = SeqT S.empty
  mconcat = F.asum
#if !MIN_VERSION_base(4,11,0)
  {-# INLINE mappend #-}
  mappend = (<|>)
#endif

instance MonadTrans SeqT where
  {-# INLINE lift #-}
  lift m = fromViewT (m >>= single)

instance Monad m => MonadLogic (SeqT m) where
  {-# INLINE msplit #-}
  msplit (toViewT -> m) = fromViewT $ do
    r <- m
    case r of
      Empty -> single Nothing
      a :< t -> single (Just (a, t))

  interleave m1 m2 = fromViewT $ interleaveViewT m1 m2

  (toViewT -> m) >>- f = fromViewT $ m >>= viewT
     (return Empty) (\a m' -> interleaveViewT (f a) (m' >>- f))

  ifte (toViewT -> t) th (toViewT -> el) = fromViewT $ t >>= viewT
    el
    (\a s -> altViewT (toViewT (th a)) (s >>= th))

  once (toViewT -> m) = fromViewT $ m >>= viewT
    (return Empty)
    (\a _ -> single a)

  lnot (toViewT -> m) = fromViewT $ m >>= viewT
    (single ()) (\ _ _ -> return Empty)

-- | A version of 'interleave' that produces a view instead of a
-- 'SeqT'. This lets us avoid @toViewT . fromViewT@ in '>>-'.
interleaveViewT :: Monad m => SeqT m a -> SeqT m a -> m (ViewT m a)
interleaveViewT (toViewT -> m1) m2 = m1 >>= viewT
  (toViewT m2)
  (\a m1' -> return $ a :< interleave m2 m1')

-- | @choose = foldr (\a s -> pure a <|> s) empty@
--
-- @choose :: Monad m => [a] -> SeqT m a@
choose :: (F.Foldable t, Monad m) => t a -> SeqT m a
choose = F.foldr cons empty
{-# INLINABLE choose #-}

-- | @chooseM = foldr (\ma s -> lift ma <|> s) empty@
--
-- @chooseM :: Monad m => [m a] -> SeqT m a@
chooseM :: (F.Foldable t, Monad m) => t (m a) -> SeqT m a
-- The idea here, which I hope is sensible, is to avoid building and
-- restructuring queues unnecessarily. We end up building only *singleton*
-- queues, which should hopefully be pretty cheap.
chooseM = F.foldr consM empty
{-# INLINABLE chooseM #-}

-- | Perform all the actions in a 'SeqT' and gather the results.
observeAllT :: Monad m => SeqT m a -> m [a]
observeAllT (toViewT -> m) = m >>= go where
  go (a :< t) = myliftM (a:) (toViewT t >>= go)
  go _ = return []
{-# INLINEABLE observeAllT #-}

-- | Perform actions in a 'SeqT' until one of them produces a
-- result. Returns 'Nothing' if there are no results.
observeT :: Monad m => SeqT m a -> m (Maybe a)
observeT (toViewT -> m) = m >>= go where
  go (a :< _) = return (Just a)
  go Empty = return Nothing
{-# INLINE observeT #-}

-- | @observeManyT n s@ performs actions in @s@ until it produces
-- @n@ results or terminates. All the gathered results are returned.
observeManyT :: Monad m => Int -> SeqT m a -> m [a]
observeManyT k m = toViewT m >>= go k where
  go n _ | n <= 0 = return []
  go _ Empty = return []
  go n (a :< t) = myliftM (a:) (observeManyT (n-1) t)
{-# INLINEABLE observeManyT #-}

-- | Get the first result in a 'Seq', if there is one.
observe :: Seq a -> Maybe a
observe = runIdentity . observeT
{-# INLINE observe #-}

-- | Get all the results in a 'Seq'.
observeAll :: Seq a -> [a]
observeAll = runIdentity . observeAllT
{-# INLINE observeAll #-}

-- | @observeMany n s@ gets up to @n@ results from a 'Seq'.
observeMany :: Int -> Seq a -> [a]
observeMany n = runIdentity . observeManyT n
{-# INLINE observeMany #-}

-- | Convert @'SeqT' m a@ to @t m a@ when @t@ is some other logic monad
-- transformer.
fromSeqT :: (Monad m, Monad (t m), MonadTrans t, Alternative (t m)) => SeqT m a -> t m a
fromSeqT (toViewT -> m) = lift m >>= \r -> case r of
  Empty -> empty
  a :< s -> pure a <|> fromSeqT s

-- | Convert @'SeqT' m a@ to @'L.LogicT' m a@.
--
-- @ toLogicT = 'fromSeqT' @
toLogicT :: Monad m => SeqT m a -> L.LogicT m a
toLogicT = fromSeqT

fromLogicT :: Monad m => L.LogicT m a -> SeqT m a
fromLogicT (L.LogicT f) = fromViewT $ f (\a v -> return (a :< fromViewT v)) (return Empty)

instance (Monad m, F.Foldable m) => F.Foldable (SeqT m) where
  foldMap f = F.foldMap (F.foldMap f) . toViewT

instance (Monad m, T.Traversable m) => T.Traversable (SeqT m) where
  -- Why is this lawful? It comes down to the fact that toViewT and
  -- fromViewT are inverses, modulo representation and detailed
  -- strictness. They witness a sort of stepwise isomorphism between
  -- SeqT and the obviously traversable
  --
  --   newtype ML m a = ML (m (ViewT m a))
  --
  -- Why can't we just use the derived Traversable instance? It doesn't
  -- respect ==. See https://github.com/dagit/logict-sequence/issues/51#issuecomment-896242724
  -- for an example.
  traverse f = fmap fromViewT . T.traverse (T.traverse f) . toViewT

-- | 'hoist' is 'hoistPre'.
instance MFunctor SeqT where
  -- Note: if `f` is not a monad morphism, then hoist may not respect
  -- (==). That is, it could be that
  --
  --   s == t = True
  --
  --  but
  --
  --   hoist f s == hoist f t = False..
  --
  -- This behavior is permitted by the MFunctor
  -- documentation, and allows us to avoid restructuring
  -- the SeqT.
  hoist f = hoistPre f

-- | This function is the implementation of 'hoist' for 'SeqT'. The passed
-- function is required to be a monad morphism.
hoistPre :: Monad m => (forall x. m x -> n x) -> SeqT m a -> SeqT n a
hoistPre f (SeqT s) = SeqT $ fmap (f . myliftM go) s
  where
    go Empty = Empty
    go (a :< as) = a :< hoistPre f as

-- | A version of `hoist` that uses the `Monad` instance for @n@
-- rather than for @m@. Like @hoist@, the passed function is required
-- to be a monad morphism.
hoistPost :: Monad n => (forall x. m x -> n x) -> SeqT m a -> SeqT n a
hoistPost f (SeqT s) = SeqT $ fmap (myliftM go . f) s
  where
      go Empty = Empty
      go (a :< as) = a :< hoistPost f as

-- | A version of 'hoist' that works for arbitrary functions, rather
-- than just monad morphisms.
hoistPreUnexposed :: forall m n a. Monad m => (forall x. m x -> n x) -> SeqT m a -> SeqT n a
hoistPreUnexposed f (toViewT -> m) = fromViewT $ f (myliftM go m)
  where
      go Empty = Empty
      go (a :< as) = a :< hoistPreUnexposed f as

-- | A version of 'hoistPost' that works for arbitrary functions, rather
-- than just monad morphisms. This should be preferred when the `Monad` instance
-- for `n` is less expensive than that for `m`.
hoistPostUnexposed :: forall m n a. (Monad m, Monad n) => (forall x. m x -> n x) -> SeqT m a -> SeqT n a
hoistPostUnexposed f (toViewT -> m) = fromViewT $ myliftM go (f m)
  where
      go Empty = Empty
      go (a :< as) = a :< hoistPostUnexposed f as

instance MonadIO m => MonadIO (SeqT m) where
  {-# INLINE liftIO #-}
  liftIO = lift . liftIO

instance MonadReader e m => MonadReader e (SeqT m) where
  -- TODO: write more thorough tests for this instance (issue #31)
  ask = lift ask
  local f (SeqT q) = SeqT $ fmap (local f . myliftM go) q
    where
      go Empty = Empty
      go (a :< s) = a :< local f s

instance MonadState s m => MonadState s (SeqT m) where
  get = lift get
  put = lift . put
  state = lift . state

instance MonadError e m => MonadError e (SeqT m) where
  -- TODO: write tests for this instance (issue #31)
  throwError = lift . throwError
  catchError (toViewT -> m) h = fromViewT $ (myliftM go m) `catchError` (toViewT . h)
    where
      go Empty = Empty
      go (a :< s) = a :< catchError s h

#if MIN_VERSION_base(4,8,0)
instance MonadZip m => MonadZip (SeqT m) where
  mzipWith f (toViewT -> m) (toViewT -> n) = fromViewT $
    mzipWith go m n
    where
      go (a :< as) (b :< bs) = f a b :< mzipWith f as bs
      go _ _ = Empty

  munzip (toViewT -> m)
    | (l, r) <- munzip (fmap go m) = (fromViewT l, fromViewT r)
    where
      go Empty = (Empty, Empty)
      go ((a, b) :< asbs) = (a :< as, b :< bs)
        where
          -- We want to be lazy so we don't force the entire
          -- structure unnecessarily. But we don't want to introduce
          -- a space leak, so we're careful to create selector thunks
          -- to deconstruct the rest of the chain.
          {-# NOINLINE muabs #-}
          {-# NOINLINE as #-}
          {-# NOINLINE bs #-}
          muabs = munzip asbs
          (as, bs) = muabs
#endif

#if MIN_VERSION_base(4,8,0)
myliftM :: Functor m => (a -> b) -> m a -> m b
myliftM = fmap
#else
myliftM :: Monad m => (a -> b) -> m a -> m b
myliftM = Monad.liftM
#endif
{-# INLINE myliftM #-}