Skip to content

Add a default definition of primitive #228

Open

Description

@treeowl

Almost all PrimMonad instances are monad transformers of other PrimMonad instances. We can give PrimState a default definition and use DefaultSignatures to give primitive one as well. We can use TypeError to produce good error messages when the defaults don't come close to making sense.

class Monad m => PrimMonad m where
  -- | State token type
  type PrimState m
  -- Default for transformed PrimMonad instances
  type PrimState m = PrimState (Arg m)

  -- | Execute a primitive operation
  primitive :: (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
  default primitive
    :: (IsTransformed m, m ~ t n, PrimMonad n, MonadTrans t, PrimState (t n) ~ PrimState n)
    => (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
  primitive = lift . primitive
  {-# INLINE primitive #-}

type family Arg (m :: * -> *) :: * -> * where
  Arg (_t n) = n

type family IsTransformed (m :: * -> *) :: Constraint where
  IsTransformed (_t (_n :: * -> *)) = ()
  IsTransformed m = TypeError
            ('Text "Cannot use defaults for instance " :$$:
             'Text "    " :<>: 'ShowType (PrimMonad m) :$$:
             'Text "because" :$$:
             'Text "    " :<>: 'ShowType m :$$:
             'Text "is not a transformed monad." )

The only error messages that aren't so great are when users write primitive implementations but forget the PrimState ones. I don't know how to fix that without ending up with a bunch of duplicate errors in some cases (which seems like a GHC issue).

Activity

  1. chessai commented on May 1, 2019

    @chessai
    Member

    I'm +1 on this, though can it instead be a top-level function, like defaultPrimitive/primitiveDefault, or something? Default signatures look so ugly on haddocks. Though a default signature does save users from an extra line of typing. The top-level thing is just something to consider, wondering what others' thoughts are.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions