How to Define Typeclass Synonyms - haskell

In an attempt to make a sane(r) alternative to Haskell's numeric type system, the devs of numeric-prelude slipped up and decided to name all of their type classes C. Aside from making the docs totally confusing, this means that I have to fully qualify all uses of the typeclasses:
import qualified Algebra.Additive (C)
import qualified Algebra.Ring (C)
...
newtype Foo a = Foo a
instance (Algebra.Additive.C a) => Algebra.Additive.C (Foo a) where ...
myadd :: (Algebra.Additive.C a) => a -> a -> a
myadd a b = ...
Also, since NumericPrelude has finer grained typeclasses, I usually have to import several different NumericPrelude modules. I can simplify this a little by defining top-level constraint synonyms:
{-# LANGUAGE ConstraintKinds #-}
module NPSynonyms (Additive) where
import qualified Algebra.Additive (C)
type Additive a = (Algebra.Additive.C a)
which allows me to make sane functions:
myadd :: (Additive a) => a -> a -> a
myadd a b = ...
However, when I need to define an instance, I still have to (also) import the original NumericPrelude class:
{-# LANGUAGE ConstraintKinds #-}
import NPSynonyms
import Algebra.Additive (C)
newtype Foo a = Foo a
instance (Additive a) => Algebra.Additive.C (Foo a) where ...
So instead of making Additive a type synonym with kind Constraint, what I'd really like is to define a typeclass synonym for the typeclass Algebra.Additive.C. Is there any way to do this in GHC 7.8, or is there any sane alternative?

you have to fully qualify
No, not fully qualify. Consider:
import qualified Algebra.Additive as Add
myadd :: Add.C a => a -> a -> a
That looks fairly readable to me.
EDIT:
Also consider making a superclass and treating that as an alias:
class (Add.C a, Ring.C a) => Num a where
instance Num Int
instance Num Word

Related

How to 'show' unshowable types?

I am using data-reify and graphviz to transform an eDSL into a nice graphical representation, for introspection purposes.
As simple, contrived example, consider:
{-# LANGUAGE GADTs #-}
data Expr a where
Constant :: a -> Expr a
Map :: (other -> a) -> Expr a -> Expr a
Apply :: Expr (other -> a) -> Expr a -> Expr a
instance Functor Expr where
fmap fun val = Map fun val
instance Applicative Expr where
fun_expr <*> data_expr = Apply fun_expr data_expr
pure val = Constant val
-- And then some functions to optimize an Expr AST, evaluate Exprs, etc.
To make introspection nicer, I would like to print the values which are stored inside certain AST nodes of the DSL datatype.
However, in general any a might be stored in Constant, even those that do not implement Show. This is not necessarily a problem since we can constrain the instance of Expr like so:
instance Show a => Show (Expr a) where
...
This is not what I want however: I would still like to be able to print Expr even if a is not Show-able, by printing some placeholder value (such as just its type and a message that it is unprintable) instead.
So we want to do one thing if we have an a implementing Show, and another if a particular a does not.
Furthermore, the DSL also has the constructors Map and Apply which are even more problematic. The constructor is existential in other, and thus we cannot assume anything about other, a or (other -> a). Adding constraints to the type of other to the Map resp. Apply constructors would break the implementation of Functor resp. Applicative which forwards to them.
But here also I'd like to print for the functions:
a unique reference. This is always possible (even though it is not pretty as it requires unsafePerformIO) using System.Mem.StableName.
Its type, if possible (one technique is to use show (typeOf fun), but it requires that fun is Typeable).
Again we reach the issue where we want to do one thing if we have an f implementing Typeable and another if f does not.
How to do this?
Extra disclaimer: The goal here is not to create 'correct' Show instances for types that do not support it. There is no aspiration to be able to Read them later, or that print a != print b implies a != b.
The goal is to print any datastructure in a 'nice for human introspection' way.
The part I am stuck at, is that I want to use one implementation if extra constraints are holding for a resp. (other -> a), but a 'default' one if these do not exist.
Maybe type classes with FlexibleInstances, or maybe type families are needed here? I have not been able to figure it out (and maybe I am on the wrong track all together).
Not all problems have solutions. Not all constraint systems have a satisfying assignment.
So... relax the constraints. Store the data you need to make a sensible introspective function in your data structure, and use functions with type signatures like show, fmap, pure, and (<*>), but not exactly equal to them. If you need IO, use IO in your type signature. In short: free yourself from the expectation that your exceptional needs fit into the standard library.
To deal with things where you may either have an instance or not, store data saying whether you have an instance or not:
data InstanceOrNot c where
Instance :: c => InstanceOrNot c
Not :: InstanceOrNot c
(Perhaps a Constraint-kinded Either-alike, rather than Maybe-alike, would be more appropriate. I suspect as you start coding this you will discover what's needed.) Demand that clients that call notFmap and friends supply these as appropriate.
In the comments, I propose parameterizing your type by the constraints you demand, and giving a Functor instance for the no-constraints version. Here's a short example showing how that might look:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
import Data.Kind
type family All cs a :: Constraint where
All '[] a = ()
All (c:cs) a = (c a, All cs a)
data Lol cs a where
Leaf :: a -> Lol cs a
Fmap :: All cs b => (a -> b) -> Lol cs a -> Lol cs b
instance Functor (Lol '[]) where
fmap f (Leaf a) = Leaf (f a)
fmap f (Fmap g garg) = Fmap (f . g) garg
Great timing! Well-typed recently released a library which allows you to recover runtime information. They specifically have an example of showing arbitrary values. It's on github at https://github.com/well-typed/recover-rtti.
It turns out that this is a problem which has been recognized by multiple people in the past, known as the 'Constrained Monad Problem'. There is an elegant solution, explained in detail in the paper The Constrained-Monad Problem by Neil Sculthorpe and Jan Bracker and George Giorgidze and Andy Gill.
A brief summary of the technique: Monads (and other typeclasses) have a 'normal form'. We can 'lift' primitives (which are constrained any way we wish) into this 'normal form' construction, itself an existential datatype, and then use any of the operations available for the typeclass we have lifted into. These operations themselves are not constrained, and thus we can use all of Haskell's normal typeclass functions.
Finally, to turn this back into the concrete type (which again has all the constraints we are interested in) we 'lower' it, which is an operation that takes for each of the typeclass' operations a function which it will apply at the appropriate time.
This way, constraints from the outside (which are part of the functions supplied to the lowering) and constraints from the inside (which are part of the primitives we lifted) are able to be matched, and finally we end up with one big happy constrained datatype for which we have been able to use any of the normal Functor/Monoid/Monad/etc. operations.
Interestingly, while the intermediate operations are not constrained, to my knowledge it is impossible to write something which 'breaks' them as this would break the categorical laws that the typeclass under consideration should adhere to.
This is available in the constrained-normal Hackage package to use in your own code.
The example I struggled with, could be implemented as follows:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE UndecidableInstances #-}
module Example where
import Data.Dynamic
import Data.Kind
import Data.Typeable
import Control.Monad.ConstrainedNormal
-- | Required to have a simple constraint which we can use as argument to `Expr` / `Expr'`.
-- | This is definitely the part of the example with the roughest edges: I have yet to figure out
-- | how to make Haskell happy with constraints
class (Show a, Typeable a) => Introspectable a where {}
instance (Show a, Typeable a) => Introspectable a where {}
data Expr' (c :: * -> Constraint) a where
C :: a -> Expr' c a
-- M :: (a -> b) -> Expr' a -> Expr' b --^ NOTE: This one is actually never used as ConstrainedNormal will use the 'free' implementation based on A + C.
A :: c a => Expr' c (a -> b) -> Expr' c a -> Expr' c b
instance Introspectable a => Show (Expr' Introspectable a) where
show e = case e of
C x -> "(C " ++ show x ++ ")"
-- M f x = "(M " ++ show val ++ ")"
A fx x -> "(A " ++ show (typeOf fx) ++ " " ++ show x ++ ")"
-- | In user-facing code you'd not want to expose the guts of this construction
-- So let's introduce a 'wrapper type' which is what a user would normally interact with.
type Expr c a = NAF c (Expr' c) a
liftExpr :: c a => Expr' c a -> Expr c a
liftExpr expr = liftNAF expr
lowerExpr :: c a => Expr c a -> Expr' c a
lowerExpr lifted_expr = lowerNAF C A lifted_expr
constant :: Introspectable a => a -> Expr c a
constant val = pure val -- liftExpr (C val)
You could now for instance write
ghci> val = constant 10 :: Expr Introspectable Int
(C 10)
ghci> (+2) <$> val
(C 12)
ghci> (+) <$> constant 10 <*> constant 32 :: Expr Introspectable Int
And by using Data.Constraint.Trivial (part of the trivial-constrained library, although it is also possible to write your own 'empty constrained') one could instead write e.g.
ghci> val = constant 10 :: Expr Unconstrained Int
which will work just as before, but now val cannot be printed.
The one thing I have not yet figured out, is how to properly work with subsets of constraints (i.e. if I have a function that only requires Show, make it work with something that is Introspectable). Currently everything has to work with the 'big' set of constraints.
Another minor drawback is of course that you'll have to annotate the constraint type (e.g. if you do not want constraints, write Unconstrained manually), as GHC will otherwise complain that c0 is not known.
We've reached the goal of having a type which can be optionally be constrained to be printable, with all machinery that does not need printing to work also on all instances of the family of types including those that are not printable, and the types can be used as Monoids, Functors, Applicatives, etc just as you like.
I think it is a beautiful approach, and want to commend Neil Sculthorpe et al. for their work on the paper and the constrained-normal library that makes this possible. It's very cool!

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.

Parametric typeclasses

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.

How to apply a polymorphic function to a Dynamic value

Is there a sane way to apply a polymorphic function to a value of type Dynamic?
For instance, I have a value of type Dynamic and I want to apply Just to the value inside the Dynamic. So if the value was constructed by toDyn True I want the result to be toDyn (Just True). The number of different types that can occur inside the Dynamic is not bounded.
(I have a solution when the types involved come from a closed universe, but it's unpleasant.)
This is perhaps not the sanest approach, but we can abuse my reflection package to lie about a TypeRep.
{-# LANGUAGE Rank2Types, FlexibleContexts, ScopedTypeVariables #-}
import Data.Dynamic
import Data.Proxy
import Data.Reflection
import GHC.Prim (Any)
import Unsafe.Coerce
newtype WithRep s a = WithRep { withRep :: a }
instance Reifies s TypeRep => Typeable (WithRep s a) where
typeOf s = reflect (Proxy :: Proxy s)
Given that we can now peek at the TypeRep of our Dynamic argument and instantiate our Dynamic function appropriately.
apD :: forall f. Typeable1 f => (forall a. a -> f a) -> Dynamic -> Dynamic
apD f a = dynApp df a
where t = dynTypeRep a
df = reify (mkFunTy t (typeOf1 (undefined :: f ()) `mkAppTy` t)) $
\(_ :: Proxy s) -> toDyn (WithRep f :: WithRep s (() -> f ()))
It could be a lot easier if base just supplied something like apD for us, but that requires a rank 2 type, and Typeable/Dynamic manage to avoid them, even if Data does not.
Another path would be to just exploit the implementation of Dynamic:
data Dynamic = Dynamic TypeRep Any
and unsafeCoerce to your own Dynamic' data type, do what you need to do with the TypeRep in the internals, and after applying your function, unsafeCoerce everything back.

Haskell -- get TypeRep from concrete type instance

I want to write a function with this type signature:
getTypeRep :: Typeable a => t a -> TypeRep
where the TypeRep will be the type representation for a, not for t a. That is, the compiler should automatically return the correct type representation at any call sites [to getTypeRep], which will have concrete types for a.
To add some context, I want to create a "Dynamic type" data type, with the twist that it will remember the top-level type, but not its parameter. For example, I want to turn MyClass a into Dynamic MyClass, and the above function will be used to create instances of Dynamic MyClass that store a representation of the type parameter a.
Well, how about using scoped type variables to select the inner component:
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Dynamic
import Data.Typeable
getTypeRep :: forall t a . Typeable a => t a -> TypeRep
getTypeRep _ = typeOf (undefined :: a)
Works for me:
*Main> getTypeRep (Just ())
()
*Main> getTypeRep (Just 7)
Integer
*Main> getTypeRep ([True])
Bool
Interesting design.
On a tangential note to Don's solution, notice that code rarely require ScopedTypeVariables. It just makes the solution cleaner (but less portable). The solution without scoped types is:
{-# LANGUAGE ExplicitForAll #-}
import Data.Typeable
helper :: t a -> a
helper _ = undefined
getTypeRep :: forall t a. Typeable a => t a -> TypeRep
getTypeRep = typeOf . helper
This function (now) exists in Data.Typeable typeRep

Resources