GeneralizedNewtypeDeriving fails for PersistFieldSql - haskell

I'm trying to define a Markdown newtype, and using GeneralizedNewtypeDeriving to automatically define new instances:
import Text.Markdown
import Yesod.Text.Markdown
import Database.Persist.Sql
newtype MarkdownNewT = MarkdownNewT { getMarkdown :: Markdown }
deriving (Eq, IsString, Monoid, PersistField, PersistFieldSql)
This fails for the PersistFieldSql with the following message:
Could not coerce from ‘m Markdown’ to ‘m MarkdownNewT’
because ‘m Markdown’ and ‘m MarkdownNewT’ are different types.
arising from the coercion of the method ‘sqlType’ from type
‘forall (m :: * -> *). Monad m => m Markdown -> SqlType’ to type
‘forall (m :: * -> *). Monad m => m MarkdownNewT -> SqlType’
Is this due to the new roles features of GHC 7.8.2? In that particular case I don't know what to do, since Markdown is itself a newtype over Text...
Or is this related with the forall on sqlType? What is the reason for this error when all other instances are successfully automatically derived?
Thanks

This looks very similar to some of the examples (in particular the Vector one) in the GHC wiki Roles2 page of things that don't work with the current role system, alas.
Basically the problem is that in
class PersistField a => PersistFieldSql a where
sqlType :: Monad m => m a -> SqlType
the monad m might be instantiated with a type constructor whose argument has nominal role, so that m Markdown and m MarkdownNewT aren't identically represented even if Markdown and MarkdownNewT themselves are - and the current role system has no way of restricting m to disallow such type constructors.

Related

Would it be possible to derive Data.Vector.Unbox via GHC's generic deriving?

It's possible to derive Storable via GHC's generic deriving mechanism: http://hackage.haskell.org/package/derive-storable (and https://hackage.haskell.org/package/derive-storable-plugin for performance). The only library I can find for deriving Data.Vector.Unbox, however, uses template Haskell: http://hackage.haskell.org/package/vector-th-unbox. It also requires the user to write a little code; it's not entirely automatic.
My question is, could a library like deriving-storable also exist for Unbox, or is this not possible due to some fundamental way in which Unbox differs from Storable? If the latter, does that mean it's also not possible to create a library that allows automatically deriving Unbox for any Storable type, as I could not find such a library.
I ask because ideally I'd like to avoid template Haskell and the manual annotations necessary for using vector-th-unbox.
Say we had some Generic_ class to convert between our own types and some uniform representation which happens to have an Unbox instance (which amounts to both MVector and Vector instances for the Unboxed variants):
class Generic_ a where
type Rep_ (a :: Type) :: Type
to_ :: a -> Rep_ a
from_ :: Rep_ a -> a
Then we can use that to obtain generic implementations of the methods of MVector/Vector:
-- (auxiliary definitions of CMV and uncoercemv at the end of this block)
-- vector imports (see gist at the end for a compilable sample)
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import Data.Vector.Generic.Mutable.Base (MVector(..))
-- MVector
gbasicLength :: forall a s. CMV s a => UM.MVector s a -> Int
gbasicLength = basicLength #UM.MVector #(Rep_ a) #s . coerce
gbasicUnsafeSlice :: forall a s. CMV s a => Int -> Int -> UM.MVector s a -> UM.MVector s a
gbasicUnsafeSlice i j = uncoercemv . basicUnsafeSlice #UM.MVector #(Rep_ a) #s i j . coerce
-- etc.
-- idem Vector
-- This constraints holds when the UM.MVector data instance of a is
-- representationally equivalent to the data instance of its generic
-- representation (Rep_ a).
type CMV s a = (Coercible (UM.MVector s a) (UM.MVector s (Rep_ a)), MVector UM.MVector (Rep_ a))
-- Sadly coerce doesn't seem to want to solve this correctly so we use
-- unsafeCoerce as a workaround.
uncoercemv :: CMV s a => UM.MVector s (Rep_ a) -> UM.MVector s a
uncoercemv = unsafeCoerce
Now if we have some generic type
data MyType = MyCons Int Bool ()
We can define a generic instance with its isomorphism to a tuple
instance Generic_ MyType where
type Rep_ MyType = (Int, Bool, ())
to_ (MyCons a b c) = (a, b, c)
from_ (a, b, c) = MyCons a b c
And from there, there is a totally generic recipe to get its Unbox instance, if you have YourType instead with its own Generic_ instance, you can take this and literally replace MyType with YourType.
newtype instance UM.MVector s MyType
= MVMyType { unMVMyType :: UM.MVector s (Rep_ MyType) }
instance MVector UM.MVector MyType where
basicLength = gbasicLength
basicUnsafeSlice = gbasicUnsafeSlice
-- etc.
-- idem (Vector U.Vector MyType)
-- MVector U.Vector & Vector UM.MVector = Unbox
instance Unbox MyType
In theory all this boilerplate could be automated with internal language features (as opposed to TemplateHaskell or CPP). But there are various issues that get in the way in the current state of things.
First, Generic_ is essentially Generic from GHC.Generics. However, the uniform representation that gets derived by GHC is not in terms of tuples (,) but in terms of somewhat ad-hoc type constructors (:+:, :*:, M1, etc.), which lack Unbox instances.
Such Unbox instances could be added to use Generic directly
the generics-eot has a variant of Generic relying on tuples that could be a direct replacement to Generic_ here.
And second, MVector and Vector have quite a few methods. To avoid having to list them all, one might expect to leverage DerivingVia (or GeneralizedNewtypeDeriving), however they are not applicable because there are a couple of polymorphic monadic methods that prevent coercions (e.g., basicUnsafeNew). For now, the easiest way I can think of to abstract this is a CPP macro. In fact the vector package uses that technique internally, and it might be reusable somehow. I believe properly addressing those issues requires a deep redesign of the Vector/MVector architecture.
Gist (not complete, but compilable): https://gist.github.com/Lysxia/c7bdcbba548ee019bf6b3f1e388bd660

How to avoid the need of an auxiliary newtype when matching this Backpack signature?

I'm using the new Backpack module system along with Cabal 2. I have the follwing signature:
{-# LANGUAGE KindSignatures #-}
signature Streamy where
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.IO.Class
data Stream :: * -> (* -> *) -> * -> *
instance Monad m => Functor (Stream o m)
instance Monad m => Applicative (Stream o m)
instance Monad m => Monad (Stream o m)
instance MonadIO m => MonadIO (Stream o m)
instance MonadTrans (Stream o)
I'm trying to match it with the concrete Stream type from streaming, like this:
import Streaming (Of(..))
import qualified Streaming as Q
type Stream o m r = Q.Stream (Of o) m r
However, this gives me the error
Illegal parameterized type synonym in implementation of abstract data.
(Try eta reducing your type synonym so that it is nullary)
It seems that the type synonym can't have parameters. I need at least one however, because the o is sitting inside the Of instead of being a direct parameter of Q.Stream.
I can solve the problem by defining an adapter newtype:
{-# language GeneralizedNewtypeDeriving #-}
newtype S o m r = S { unS :: Q.Stream (Of o) m r }
deriving (Functor,Applicative,Monad,MonadIO,MonadTrans)
type Stream = S
Is there another way that doesn't require defining the newtype?
It seems that there isn't a way to avoid the newtype. The Backpack thesis clearly states that type synonyms are required to be nullary (section 6.2.4 "Subtyping rules"):
the implementing type synonyms are required to be nullary: for
example, type M a = a is not a valid implementation of the abstract
data M a, but type M = Maybe :: * -> * is. This restriction stems
from an old design decision in Haskell to not support type level
lambdas. This restriction greatly helps type inference, since given
the type equality t a = s b, we can now conclude that t = s and a = b
(this property is called generativity).
Also related, in section B.2 "Challenges":
Translucency: A feature not supported in Backpack’14 but supported in
Backpack’17 is the ability to use a type synonym to implement an
abstract data type. This introduces a form of “translucency”, where
the abstract data type is opaque while the implementation is unknown,
and transparent afterwards. For example, in Section 2.3, we
demonstrated how we could instantiate a generic regular expression
matcher to match on strings. Inside the implementation of the matcher,
we knew nothing about the abstract type Str; after instantiating it,
the accept function transparently accepts String arguments.

Type variable is not in scope when defining type class

I'm writing a type class à la mtl-style transformers. Looks like this:
class (Monad m, Stream s m t) => MonadStuff s m | m -> s where
-- function signatures go here…
I'm trying to say by that that m should be instance of Monad and there
should be instance of Stream s m t, where t doesn't really matter but
s and m are from the right side of the definition (after =>).
Haskell says:
Not in scope: type variable ‘t’
So, obviously I cannot do that. Or can I? Should I remove Stream s m t
constraint and add it to every function in the class instead or is there
another way?
If it's really true that it doesn't really matter what t is, then perhaps you can ask the person writing the instance to choose it:
{-# LANGUAGE TypeFamilies #-}
class (Monad m, Stream s m (StuffType m)) => MonadStuff s m | m -> s where
type StuffType m
Or, since you already have MPTCs and fundeps turned on, you could consider doing this, which requires no extra extensions but is otherwise basically identical:
class (Monad m, Stream s m t) => MonadStuff s m t | m -> s t where
However, I am suspicious that in fact the choice of t does matter: unless Stream has a fundep that is at least as informative as m s -> t, you will not be able to use this constraint in a meaningful way. In that case, you should move the constraint into the signatures of the methods that mention t or will be using the Stream methods.

Convert from type `T a` to `T b` without boilerplate

So, I have an AST data type with a large number of cases, which is parameterized by an "annotation" type
data Expr a = Plus a Int Int
| ...
| Times a Int Int
I have annotation types S and T, and some function f :: S -> T. I want to take an Expr S and convert it to an Expr T using my conversion f on each S which occurs within an Expr value.
Is there a way to do this using SYB or generics and avoid having to pattern match on every case? It seems like the type of thing that this is suited for. I just am not familiar enough with SYB to know the specific way to do it.
It sounds like you want a Functor instance. This can be automatically derived by GHC using the DeriveFunctor extension.
Based on your follow-up question, it seems that a generics library is more appropriate to your situation than Functor. I'd recommend just using the function given on SYB's wiki page:
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, FlexibleContexts #-}
import Data.Generics
import Unsafe.Coerce
newtype C a = C a deriving (Data,Typeable)
fmapData :: forall t a b. (Typeable a, Data (t (C a)), Data (t a)) =>
(a -> b) -> t a -> t b
fmapData f input = uc . everywhere (mkT $ \(x::C a) -> uc (f (uc x)))
$ (uc input :: t (C a))
where uc = unsafeCoerce
The reason for the extra C type is to avoid a problematic corner case where there are occurrences of fields at the same type as a (more details on the wiki). The caller of fmapData doesn't need to ever see it.
This function does have a few extra requirements compared to the real fmap: there must be instances of Typeable for a, and Data for t a. In your case t a is Expr a, which means that you'll need to add a deriving Data to the definition of Expr, as well as have a Data instance in scope for whatever a you're using.

Is there a typeclass for references similar to the MArray class for mutable arrays?

The MArray class provides generic functions for working with mutable arrays of various sorts in both ST and IO contexts. I haven't been able to find a similar class for working with both STRefs and IORefs. Does such a thing exist?
The ref-fd package provides it:
class Monad m => MonadRef r m | m -> r where
[...]
or with type families, ref-tf:
class Monad m => MonadRef m where
type Ref m :: * -> *
[...]
Another answer suggested the monad-statevar package which doesn't have the functional dependency. It also has separate HasGet and HasPut members and no abstraction over the newRef functionality.
Aside from the different methods in each, the functional dependency is a design trade-off. Consider the following two simplified classes:
class MRef1 r m where
newRef1 :: a -> m (r a)
readRef1 :: r a -> m a
class MRef2 r m | m -> r where
newRef2 :: a -> m (r a)
readRef2 :: r a -> m a
With MRef1, both the monad type and the reference type can vary freely, so the following code has a type error:
useMRef1 :: ST s Int
useMRef1 = do
r <- newRef1 5
readRef1 r
No instance for (MRef1 r0 (ST s)) arising from a use of `newRef1'
The type variable `r0' is ambiguous
We have to add an extra type signature somewhere to say that we want to use STRef.
In contrast, the same code works fine for MRef2 without any extra signature. The signature on the definition saying that the whole code has type ST s Int, combined with the functional dependency m -> r means that there is only one r type for a given m type and so the compiler knows that our existing instance is the only possible one and we must want to use STRef.
On the flip side, suppose we want to make a new kind of reference, e.g. STRefHistory that tracks all the values that have ever been stored in it:
newtype STRefHistory s a = STRefHistory (STRef s [a])
The MRef1 instance is fine because we are allowed multiple reference types for the same monad type:
instance MRef1 (STRefHistory s) (ST s) where
newRef1 a = STRefHistory <$> newSTRef [a]
readRef1 (STRefHistory r) = head <$> readSTRef r
but the equivalent MRef2 instance fails with:
Functional dependencies conflict between instance declarations:
instance MRef2 (STRef s) (ST s) -- Defined at mref.hs:28:10
instance MRef2 (STRefHistory s) (ST s) -- Defined at mref.hs:43:10
I also mentioned the type family version, which is quite similar in expressive power to the functional dependency; the reference type is a "type function" of the monad type so there can again only be one per monad. The syntax ends up being a bit different and in particular you can just say MonadRef m in constraints, without stating what the reference type is within the constraint.
It's also plausible to have the reversed functional dependency:
class MRef2 r m | r -> m where
so that each reference type can live in just one monad, but you can still have several reference types for a monad. Then you'd need type signatures on your references but not on your monadic computations as a whole.
Control.Monad.StateVar has a typeclass which lets you get and put IORefs and STRefs identically.

Resources