Parametric typeclasses - haskell

Is there a way to declare a generic parametrized type Conf that offers/provides a function frames depending on the type parameter d, like
{-# LANGUAGE GeneralizedNewtypeDeriving
, MultiParamTypeClasses
, FunctionalDependencies #-}
import Control.Applicative
import Control.Monad
import Control.Monad.Identity
import Control.Monad.Trans.Class
import Control.Monad.Trans.State
import Control.Monad.Trans.Except
data MyConf d = MyConf { frames :: [d] } -- my parametric type
-- define a class to expose the interface in monads
class ConfM d m | m -> d where
getFrames :: m [d]
-- wrap StateT to include MyConf and allow instance of ConfM
newtype MyStateT d m a = MyStateT { runMyStateT :: StateT (MyConf d) m a }
deriving (Functor, Applicative, Monad, MonadTrans)
-- expose the interface over selected transformers
instance Monad m => ConfM d (MyStateT d m) where
getFrames = MyStateT $ fmap frames get
instance (ConfM d m, Monad m) => ConfM d (ExceptT a m) where
getFrames = lift getFrames
so that then one can write something like:
-- hide the gory implementation details
type MyMonad d = ExceptT A (MyStateT d B) C
class SomeClass a
-- this is the desired goal:
-- to concisely write an 'algorithm' in MyMonad only once
-- but for all possible choices of d from SomeClass
example :: SomeClass d => MyMonad d
example = do
fs <- getFrames
-- do SomeClass stuff with d
return ()
-- assume Int is instance of SomeClass
instance SomeClass Int
-- give me an instance of the above generic 'algorithm'
exampleInt :: MyMonad Int
exampleInt = example
-- assuming for example
type A = ()
type B = Identity
type C = ()
In the above code I am stuck at:
test.hs:23:25:
Illegal instance declaration for ‘ConfM d (MyStateT d m)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for ‘ConfM d (MyStateT d m)’
test.hs:26:38:
Illegal instance declaration for ‘ConfM d (ExceptT a m)’
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for ‘ConfM d (ExceptT a m)’
With additional FlexibleInstances
test.hs:27:14:
Illegal instance declaration for ‘ConfM d (ExceptT
The coverage condition fails in class ‘ConfM’
for functional dependency: ‘m -> d’
Reason: lhs type ‘ExceptT a m’ does not determine
Using UndecidableInstances might help
In the instance declaration for ‘ConfM d (ExceptT a
So I need UndecidableInstances.

Your question seems a bit vague, but it sounds like a potential use case for a multi-parameter typeclass with a functional dependency.
{-# LANGUAGE MultiParamTypeClasses
, FunctionalDependencies #-}
class Monad m => MyClass d m | m -> d where
getDs :: m [d]
Then MyClass d m means that m is a Monad and that getDs can be used to produce a value of type m [d]. The purpose of the functional dependency is to indicate that m determines d. There is exactly one instance declaration of MyClass for each m, and that class must determine what d is. So you could write an instance like
instance MyClass Int IO where ...
(which would then be the only one allowed for IO), but not something wishy-washy like
instance MyClass d IO where ...
because the latter does not determine d.
You might find my choice of argument order for MyClass a bit strange. There is some method to this madness. The main reason for it is that MyClass can be partially applied. Partially applying it to m isn't too useful, because that leaves a constraint that can only be satisfied by one possible argument. Partially applying it to d, on the other hand, could be useful, because there could be multiple choices of m for a given choice of d. Thus given {-# LANGUAGE ConstraintKinds #-},
type MakesInts = MyClass Int
is a potentially useful constraint. I believe using this order may also help avoid the need for UndecidableInstances in some cases, but I'm not certain.
An alternative others mentioned is to use an associated type family.
{-# LANGUAGE TypeFamilies #-}
class Monad m => MyClass m where
type Available m
getDs :: m [Available m]
This does essentially the same thing, but
Anyone writing an instance of MyClass must include a line like, e.g., type Available IO = Int.
Anyone placing a constraint on the Available type will need to use Available in the constraint, and will need FlexibleContexts (not a big deal).
The type family offers access to the associated type.
Type families are expressed in GHC Core (AKA System FC), so they're better-behaved than functional dependencies in some regards.
1 (especially) and 2 are arguably downsides of the type family approach; 3 and 4 are upsides. This largely comes down to a question of taste.

Related

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.

What is the difference between `DeriveAnyClass` and an empty instance?

Using the cassava package, the following compiles:
{-# LANGUAGE DeriveGeneric #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic)
instance ToNamedRecord Foo
However, the following does not:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
import Data.Csv
import GHC.Generics
data Foo = Foo { foo :: Int } deriving (Generic, ToNamedRecord)
The compiler reports:
test.hs:7:50:
No instance for (ToNamedRecord Int)
arising from the first field of ‘Foo’ (type ‘Int’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (ToNamedRecord Foo)
This leaves me with two questions: Why isn't the second version identical to the first? And why is the compiler hoping to find an instance for ToNamedRecord Int?
NB: As pointed out by David in the comments, GHC has been updated since I wrote this. The code as written in the question compiles and works correctly. So just imagine everything below is written in the past tense.
The GHC docs say:
The instance context will be generated according to the same rules
used when deriving Eq (if the kind of the type is *), or the rules for
Functor (if the kind of the type is (* -> *)). For example
instance C a => C (a,b) where ...
data T a b = MkT a (a,b) deriving( C )
The deriving clause will
generate
instance C a => C (T a b) where {}
The constraints C a and C (a,b) are generated from the data constructor arguments, but the
latter simplifies to C a.
So, according to the Eq rules, your deriving clause generates...
instance ToNamedRecord Int => ToNamedRecord Foo where
... which is not the same as...
instance ToNamedRecord Foo where
... in that the former is only valid if there's an instance ToNamedRecord Int in scope (which is appears there isn't in your case).
But I find the spec to be somewhat ambiguous. Should the example really generate that code, or should it generate instance (C a, C (a, b)) => instance C (T a b) and let the solver discharge the second constraint? It appears, in your example, that it's generating such constraints even for fields with fully-concrete types.
I hesitate to call this a bug, because it's how Eq works, but given that DeriveAnyClass is intended to make it quicker to write empty instances it does seem unintuitive.

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.

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.

Liberal coverage condition introduced in GHC 7.7 breaks code valid in GHC 7.6

The idea
I'm writing a DSL, which compiles to Haskell.
Users of this language can define own immutable data structures and associated functions. By associated function I mean a function, which belongs to a data structure.
For example, user can write (in "pythonic" pseudocode):
data Vector a:
x,y,z :: a
def method1(self, x):
return x
(which is equivalent to the following code, but shows also, that associated functions beheva like type classes with open world assumption):
data Vector a:
x,y,z :: a
def Vector.method1(self, x):
return x
In this example, method1 is a function associated with Vector data type, and can be used like v.testid(5) (where v is instance of Vector data type).
I'm translating such code to Haskell code, but I'm facing a problem, which I'm trying to solve for a long time.
The problem
I'm trying to move the code from GHC 7.6 over GHC 7.7 (which is pre-release of 7.8) (Newer versions can be compiled from sources). The code works perfectly under GHC 7.6, but does not under GHC 7.7.
I want to ask you how can I fix it to make it working in the new version of the compiler?
Example code
Lets see a simplified version of generated (by my compiler) Haskell code:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
import Data.Tuple.OneTuple
------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)
-- the Vector_testid is used as wrapper over a function "testid".
newtype Vector_testid a = Vector_testid a
------------------------------
-- sample function, which is associated to data type Vector
------------------------------
testid (v :: Vector a) x = x
------------------------------
-- problematic function (described later)
------------------------------
testx x = call (method1 x) $ OneTuple "test"
------------------------------
-- type classes
------------------------------
-- type class used to access "method1" associated function
class Method1 cls m func | cls -> m, cls -> func where
method1 :: cls -> m func
-- simplified version of type class used to "evaluate" functions based on
-- their input. For example: passing empty tuple as first argument of `call`
-- indicates evaluating function with default arguments (in this example
-- the mechanism of getting default arguments is not available)
class Call a b where
call :: a -> b
------------------------------
-- type classes instances
------------------------------
instance (out ~ (t1->t1)) => Method1 (Vector a) Vector_testid out where
method1 = (Vector_testid . testid)
instance (base ~ (OneTuple t1 -> t2)) => Call (Vector_testid base) (OneTuple t1 -> t2) where
call (Vector_testid val) = val
------------------------------
-- example usage
------------------------------
main = do
let v = Vector (1::Int) (2::Int) (3::Int)
-- following lines equals to a pseudocode of ` v.method1 "test" `
-- OneTuple is used to indicate, that we are passing single element.
-- In case of more or less elements, ordinary tuples would be used.
print $ call (method1 v) $ OneTuple "test"
print $ testx v
The code compiles and works fine with GHC 7.6. When I'm trying to compile it with GHC 7.7, I'm getting following error:
debug.hs:61:10:
Illegal instance declaration for
‛Method1 (Vector a) Vector_testid out’
The liberal coverage condition fails in class ‛Method1’
for functional dependency: ‛cls -> func’
Reason: lhs type ‛Vector a’ does not determine rhs type ‛out’
In the instance declaration for
‛Method1 (Vector a) Vector_testid out’
The error is caused by new rules of checking what functional dependencies can do, namely liberal coverage condition (as far as I know, this is coverage condition relaxed by using -XUndecidableInstances)
Some attemps to fix the problem
I was trying to overcome this problem by changing the definition of Method1 to:
class Method1 cls m func | cls -> m where
method1 :: cls -> m func
Which resolves the problem with functional dependencies, but then the line:
testx x = call (method1 x) $ OneTuple "test"
is not allowed anymore, causing a compile error (in both 7.6 and 7.7 versions):
Could not deduce (Method1 cls m func0)
arising from the ambiguity check for ‛testx’
from the context (Method1 cls m func,
Call (m func) (OneTuple [Char] -> s))
bound by the inferred type for ‛testx’:
(Method1 cls m func, Call (m func) (OneTuple [Char] -> s)) =>
cls -> s
at debug.hs:50:1-44
The type variable ‛func0’ is ambiguous
When checking that ‛testx’
has the inferred type ‛forall cls (m :: * -> *) func s.
(Method1 cls m func, Call (m func) (OneTuple [Char] -> s)) =>
cls -> s’
Probable cause: the inferred type is ambiguous
EDIT:
It is also impossible to solve this issue using type families (as far as I know). If we replace Method1 type class and instances with following code (or simmilar):
class Method1 cls m | cls -> m where
type Func cls
method1 :: cls -> m (Func cls)
instance Method1 (Vector a) Vector_testid where
type Func (Vector a) = (t1->t1)
method1 = (Vector_testid . testid)
We would get obvious error Not in scope: type variable ‛t1’, because type families does not allow to use types, which does not appear on LHS of type expression.
The final question
How can I make this idea work under GHC 7.7? I know the new liberal coverage condition allows GHC devs make some progress with type checking, but it should somehow be doable to port idea working in GHC 7.6 over never compiler version.
(without forcing user of my DSL to introduce any further types - everything so far, like type class instances, I'm genarating using Template Haskell)
This is not a bug in GHC 7.7. It was a long-standing bug in GHC when it allowed instances
that violate functional dependencies. It seems, fortunately, that this problem is finally fixed. The error message emitted by GHC 7.7 is quite detailed, pointing out the problem with your instance Method1 (Vector a) Vector_testid out. Recall the meaning of functional
dependencies. Given
class C a b | a -> b
it follows that if the types a, b and b1 are such that C a b and C a b1
both hold, it must be true that b and b1 are the same. Let's look at your instance:
Method1 (Vector a) Vector_testid (t1->t1)
If we have types b and b1 that satisfy Method1 (Vector Int) Vector_testid (b->b)
and Method1 (Vector a) Vector_testid (b1->b1), nothing at all implies that b and b1 must be the same. Hence your instance is ill-formed. The fact that GHC 7.6 and before accepted the program was a well-known bug in GHC (discussed about every year).
What you seem to be trying is to define something like
Method1 (Vector a) Vector_testid (forall t. t -> t)
Alas, this syntax is not allowed, although many worksrounds exist. One, for example, involves the Apply class (see the HList paper, for example). A simpler way is as follows
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
-- import Data.Tuple.OneTuple
newtype OneTuple x = OneTuple x deriving Show
------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)
-- testx x = call (method1 x) $ OneTuple "test"
testx x = call x Method1 $ OneTuple "test"
-- associate methods to classes
class Methods cls m x y | cls m x -> y where
call :: cls -> m -> x -> y
instance Methods (Vector a) Method1 x x where
call self _ x = x
data Method1 = Method1 -- method label

Resources