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

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.

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

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.

How to create an interface for a stateful component where the state type is opaque?

-- InternalComponent.hs
data ComponentState = ComponentState ...
instance Default ComponentState where ...
componentFunction :: (MonadState InternalComponentState m) => a -> m a
-- Program.hs
data ProgramState = forall cs. ProgramState {
componentState :: cs,
...
}
newtype MyMonad a = MyMonad { runMyMonad :: StateT ProgramState IO a }
myFunction a = do
s <- get
let cs = componentState s
let (r, cs') = runState (componentFunction a) cs
put $ s { componentState = cs' }
return r
What I want is to be able to use the componentFunction inside of MyMonad (in myFunction, as presented in the example), without being particularly interested in the actual type of the state the component requires. Keeping the component state inside of my own state isn't a requirement, but that's as far as my ability to use state in Haskell goes.
This can really be viewed as an equivalent of an implementation of a stateful interface in another programming language: instantiation of the interface with some implementation provides default state value, and every function called through that interface can modify that state. In any point isn't the user presented with implementation details.
In case it's not clear, the above example fails because the implementation of myFunction can't prove that the record selector provides an appropriate type (because it's an existential); at least that's how I understand it.
You can parametrize ProgramState by the type of the component state(s), e.g. have
data ProgramState cs = ProgramState { componentState :: cs }
This would mean you'll also have to expose the ComponentState type from InternalComponent.hs, but not the constructors. This way you give the type checker something to play with, but don't expose any internals to the users of InternalComponent.
First, I'd suggest to read Combining multiple states in StateT, just to see other available options.
Since in the case of nested states we need to update values inside more complex objects, using lens can make life a lot easier (see also this tutorial). A value of type Lens' s a knows how to reach a particular value of type a inside s and how to modify it (that is, creating a new value of type s that is the same, except for a modified a). Then we can define a helper function
runInside :: (MonadState s m) => Lens' s a -> State a r -> m r
runInside lens s = lens %%= (runState s)
Given a lens and a stateful computation on a, we can lift such a computation to a stateful computation parametrized by s. The library allows us to generate lenses using Template Haskell, for example:
{-# LANGUAGE RankNTypes, TemplateHaskell #-}
import Control.Lens.TH
data ProgramState cs = ProgramState { _componentState :: cs }
$(makeLenses ''ProgramState)
will generate componentState :: Lens' ProgramState cs (actually the generated function will be slightly more more generic). Combining them together we get
runInside componentState :: MonadState (ProgramState a) m => State a r -> m r
Using Typeable we could go even further and create a map that automatically creates or keeps a state for whatever type it is asked for. I'd not recommend this approach in general, as it sort-of avoids Haskell's strong type system checks, but it might be useful in some cases.
{-# LANGUAGE ExistentialQuantification, ScopedTypeVariables, RankNTypes #-}
import Control.Lens
import Control.Lens.TH
import Control.Monad.State
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Typeable
data Something = forall a . Typeable a => Something a
type TypeMap = Map TypeRep Something
We defined a generic untyped container that can hold whatever is Typeable and a map that maps representation of types to their values.
We'll need some class to provide default/starting values:
class Default a where
getDefault :: a
-- just an example
instance Default Int where
getDefault = 0
Finally, we can create a lens that given an arbitrary Typeable type, it focuses on its value in the map by looking up its type representation:
typeLens :: forall t . (Typeable t, Default t) => Lens' TypeMap t
typeLens = lens get set
where
set map v = Map.insert (typeOf v) (Something v) map
get map = case Map.lookup (typeRep (Proxy :: Proxy t)) map of
Just (Something v) | Just r <- cast v -> r
_ -> getDefault
So you could have TypeMap somewhere in your state and let all stateful computations use it, regardless of what state they need.
However, there is a big warning: If two unrelated computations happen to use the same type for their state, they'll share the value with very likely disastrous results! So using explicit records for states of different parts of your computations is going to be much safer.

GeneralizedNewtypeDeriving fails for PersistFieldSql

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.

Class contraints for monads and monad functions

I am trying to write a new monad that only can contain a Num. When it fails, it returns 0 much like the Maybe monad returns Nothing when it fails.
Here is what I have so far:
data (Num a) => IDnum a = IDnum a
instance Monad IDnum where
return x = IDnum x
IDnum x >>= f = f x
fail :: (Num a) => String -> IDnum a
fail _ = return 0
Haskell is complaining that there is
No instance for (Num a) arising from a use of `IDnum'
It suggests that I add a add (Num a) to the context of the type signature for each of my monad functions, but I tried that it and then it complains that they need to work "forall" a.
Ex:
Method signature does not match class; it should be
return :: forall a. a -> IDnum a
In the instance declaration for `Monad IDnum'
Does anyone know how to fix this?
The existing Monad typeclass expects your type to work for every possible type argument. Consider Maybe: in Maybe a, a is not constrained at all. Basically you can't have a Monad with constraints.
This is a fundamental limitation of how the Monad class is defined—I don't know of any way to get around it without modifying that.
This is also a problem for defining Monad instances for other common types, like Set.
In practice, this restriction is actually pretty important. Consider that (normally) functions are not instances of Num. This means that we could not use your monad to contain a function! This really limits important operations like ap (<*> from Applicative), since that depends on a monad containing a function:
ap :: Monad m => m (a -> b) -> m a -> m b
Your monad would not support many common uses and idioms we've grown to expect from normal monads! This would rather limit its utility.
Also, as a side-note, you should generally avoid using fail. It doesn't really fit in with the Monad typeclass: it's more of a historic accident. Most people agree that you should avoid it in general: it was just a hack to deal with failed pattern matches in do-notation.
That said, looking at how to define a restricted monad class is a great exercise for understanding a few Haskell extensions and learning some intermediate/advanced Haskell.
Alternatives
With the downsides in mind, here are a couple of alternatives—replacements for the standard Monad class that do support restricted monads.
Constraint Kinds
I can think of a couple of possible alternatives. The most modern one would be taking advantage of the ConstraintKind extension in GHC, which lets you reify typeclass constraints as kinds. This blog post details how to implement a restricted monad using constraint kinds; once I've read it, I'll summarize it here.
The basic idea is simple: with ConstraintKind, we can turn our constrain (Num a) into a type. We can then have a new Monad class which contains this type as a member (just like return and fail are members) and allows use to overload the constraint with Num a. This is what the code looks like:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import Prelude hiding (Monad (..))
import GHC.Exts
class Monad m where
type Restriction m a :: Constraint
type Restriction m a = ()
return :: Restriction m a => a -> m a
(>>=) :: Restriction m a => m a -> (a -> m b) -> m b
fail :: Restriction m a => String -> m a
data IDnum a = IDnum a
instance Monad IDnum where
type Restriction IDnum a = Num a
return = IDnum
IDnum x >>= f = f x
fail _ = return 0
RMonad
There is an existing library on hackage called rmonad (for "restricted monad") which provides a more general typeclass. You could probably use this to write your desired monad instance. (I haven't used it myself, so it's a bit hard to say.)
It doesn't use the ConstraintKinds extension and (I believe) supports older versions of GHC. However, I think it's a bit ugly; I'm not sure that it's the best option any more.
Here's the code I came up with:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import Prelude hiding (Monad (..))
import Control.RMonad
import Data.Suitable
data IDnum a = IDnum a
data instance Constraints IDnum a = Num a => IDnumConstraints
instance Num a => Suitable IDnum a where
constraints = IDnumConstraints
instance RMonad IDnum where
return = IDnum
IDnum x >>= f = f x
fail _ = withResConstraints $ \ IDnumConstraints -> return 0
Further Reading
For more details, take a look at this SO question.
Oleg has an article about this pertaining specifically to the Set monad, which might be interesting: "How to restrict a monad without breaking it".
Finally, there are a couple of papers you could also read:
The Constrained-Monad Problem
Generic Monadic Constructs for Embedded Languages
This answer will be brief, but here's another alternative to go along with Tikhon's. You can apply a codensity transformation to your type to basically get a free monad for it. Just use it (in the below code it's IDnumM) instead of your base type, then convert the final value to your base type at the end (in the below code, you would use runIDnumM). You can also inject your base type into the transformed type (in the below code, that would be toIDnumM).
A benefit of this approach is that it works with the standard Monad class.
data Num a => IDnum a = IDnum a
newtype IDnumM a = IDnumM { unIDnumM :: forall r. (a -> IDnum r) -> IDnum r }
runIDnumM :: Num a => IDnumM a -> IDnum a
runIDnumM (IDnumM n) = n IDnum
toIDnumM :: Num a => IDnum a -> IDnumM a
toIDnumM (IDnum x) = IDnumM $ \k -> k x
instance Monad IDnumM where
return x = IDnumM $ \k -> k x
IDnumM m >>= f = IDnumM $ \k -> m $ \x -> f x `unIDnumM` k
There is an easier way to do this. One can use multiple functions. First, write one in the Maybe monad. The Maybe monad returns Nothing upon failure. Second, write a function that returns the Just value if not Nothing or some safe value if Nothing. Third, write a function that composes those two functions.
This produces the desired result while being much easier to write and understand.

Resources