haskell / haskell/primitive

Add a default definition of primitive

Open
#228 1 comment 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Haskell
Stars
123
Forks
60
PR merge metrics
No merged PRs in 30d

Description

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.

```haskell
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).

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.