Using RankNTypes one can enforce various kinds of parametricity. For example, A id :: A:
newtype A = A { unA :: forall a. a -> a }
But how about cases where we only care about the parametricity of the function on its argument? For a specific kind of case, the following will work:
newtype X b = X { unX :: forall a. a -> (a, b) }
For example, X (\a -> (a, ())) :: X ().
I would like to understand how to (or whether one can) construct a parametricity test that works more generally for functions of the form \a -> (a, f a), where f may be constant (as above) or potentially parametric itself. This can't be accomplished with X. E.g., X (\a -> (a, id a)) is a type error. Can this be done?
Edit: I'd like to repose or elaborate on the question somewhat. Suppose we have a type of parameterized state transformers:
type PState i o a = i -> (a, o)
Suppose also that we are interested in statically enforcing that the a in an arbitrary m :: PState i o a does not depend on i in any way. In other words, is it possible to define a function f such that f m is well typed when m's value doesn't depend on the input (and in that case evaluates to m), and is not well typed otherwise?
You'll need to make an explicit type-level function to accomplish this. Normally quantified Type -> Type variables are actually assumed to be type constructors (injective functions), which is not sufficient here. But it is possible to have noninjective ones too, they're just called type families. The flip side to this is that you need some separate means of actually indexing which one you want, because type inference wouldn't work without that.
{-# LANGUAGE TypeFamilies, KindSignatures, EmptyDataDecls, TypeInType
, RankNTypes, UnicodeSyntax #-}
import Data.Kind
type family MyTyFun (f :: Type) (a :: Type) :: Type
newtype GState f = GState { unGS :: ∀ a . a -> (a, MyTyFun f a) }
data Af
type instance MyTyFun Af a = ()
type A = GState Af
data Xf b
type instance MyTyFun (Xf b) a = b
type X b = GState (Xf b)
data Wf
type instance MyTyFun Wf a = a
type W = GState Wf
> unGS (GState (\a -> (a, a)) :: W) 4
(4,4)
Related
Apologies for the potentially vague question title - I'm not sure how to phrase it because I have a pretty poor understanding of what the problem is.
Basically, how do I make the following compile? :-p
{-# LANGUAGE MultiParamTypeClasses #-}
class (Monad m) => MyClass m a where
valM :: m (Maybe a)
val :: m a
f :: (MyClass m a) => (m a -> IO a) -> IO (a, Maybe a)
f g = do
x <- g val
yM <- g valM
return (x, yM)
GHC (v8.2.2) complains that a is a rigid type variable and can't seem to cope with the idea that (g val) and (g valM) could produce values of different types. I've tried using RankNTypes but to no avail.
Is there an extension I can use to help the compiler, or is there something conceptually broken with what I'm trying to do from a type-inference point of view?
You’re right that you need RankNTypes, but you’re missing a forall. The correct type for f is:
f :: MyClass m a => (forall b. m b -> IO b) -> IO (a, Maybe a)
…since the function passed to f must work for any result type, and it shouldn’t be related to the a in the result.
It’s also potentially worth noting that this sort of function is also known as a natural transformation, and the natural-transformation package provides a (~>) type alias for such functions:
type (~>) f g = forall a. f a -> g a
Therefore, using that type alias, you could also write f like this:
f :: MyClass m a => (m ~> IO) -> IO (a, Maybe a)
Consider the following Haskell code:
import Data.Coerce
newtype Decorated s a = Decorated a
fancyFunction :: Ctx s => f (Decorated s a) -> r
fancyFunction = ...
instance Ctx s => SomeClass (Decorated s a)
myFunction :: Functor f => f a -> r
myFunction = fancyFunction . fmap coerce
I'd like to make myFunction faster by replacing fmap coerce with coerce. The rationale is that coerce behaves like id and one of the functor laws is fmap id = id.
The only way I can see of doing this is to add Coercible (f a) (f (Decorated s a)) to the context but it refers to s which is not referred to anywhere else. Even worse, if a is bound in a universal type, I cannot express the constraint. Is there a constraint I could express in terms of f only to let me use coerce to convert between f a and f (Decorated s a)?
Is this something that the compiler figures out on its own from the fact that f is a functor? If so, does it also work with bifunctors, traversables and bitraverables?
Unfortunately, Coercible (f a) (f (Decorated s a)) really what you want in your constraint given the current state of GHC. Now, the fact that s and a don't show up elsewhere is not something good - it means GHC won't know what to do with them (they are ambiguous)! I won't get into that...
Depending on the role of the type parameter fed to the type constructor f, Coercible a b may or may not imply Coercible (f a) (f b). In this case, we'd want that role to be nominal - but there isn't (yet at least) a way to express this in a constraint. To explain what I mean, consider the following two data definitions:
{-# LANGUAGE TypeFamilies #-}
import Data.Coerce
-- type role of `a` is "representational"
data Data1 a = Data1 a
-- type role of `a` is "nominal"
data Data2 a = Data2 (TypeFunction a)
type family TypeFunction x where
TypeFunction Bool = Char
TypeFunction _ = ()
Then, while it is true that Coercible a b entails Coercible (Data1 a) (Data1 b), it does not entail Coercible (Data2 a) (Data2 b). To make this concrete, load up the above in GHCi, then try:
ghci> newtype MyInt = My Int
ghci> let c1 = coerce :: (Data1 MyInt) -> (Data1 Int)
ghci> let c2 = coerce :: (Data2 MyInt) -> (Data2 Int) -- This doesn't work!
Unfortunately, there is no built-in constraint based way of enforcing that the role of a type variable is representational. You can make your own classes for this, as Edward Kmett has done, but GHC doesn't automatically create instances of some of these classes the way class instances for Coercible are.
This led to this trac ticket where they discuss the possibility of having a class Representational f with instances generated like for Coercible which could have things like
instance (Representational f, Coercible a b) => Coercible (f a) (f b)
If this was actually a thing today, all you would need in your constraint would be Representational f. Furthermore, as Richard Eisenberg observes on the ticket, we really ought to be able to figure out that a in f a has a representational role for any reasonable functor f. Then, we might not even need any constraint on top of Functor f as Representational could be a superclass of Functor.
Here is a good discussion of the current limitations of roles.
Now that you have QuantifiedConstraints, I think you can do this:
type Parametric f = (forall a b. (Coercible a b => Coercible (f a) (f b)) :: Constraint)
newtype Foo = Foo Int
myFunction :: (Parametric f) => f Foo -> f Int
myFunction = coerce
test :: [Int]
test = myFunction [Foo 1, Foo 2, Foo 3]
This is nice, because an instance of Parametric f witnesses that f is an endofunctor on a category where the objects are types and a morphism between types A and B is an instance of Coercible A B.
I want to make an instance declaration, but the free type variable is not the last variable. For example, I have a class declaration
class Poppable m where
tryPop :: m a -> Maybe (a, m a)
Now I want to make Q.PSQ (priority queue) an instance of Poppable. Specifically I want something like this:
instance (Ord p) => Poppable (\a -> Q.PSQ a p) where
tryPop = fmap (first Q.key) . Q.minView
However, this is not legal Haskell code. If the order of arguments to PSQ were switched, then I would have no problem:
instance (Ord p) => Poppable (Q.PSQ p) where
tryPop = fmap (first Q.key) . Q.minView
How do I switch the order of arguments for the instance declaration?
Now I could wrap PSQ with a newtype:
newtype PSQ'' a b = PSQ'' (Q.PSQ b a)
However this seems clunky to me because I have to constantly wrap/unwrap it. Is there an easier way?
*
I tried using data/type families, but both give errors.
(1) Using a data family declaration:
data family PSQ' a b
data instance PSQ' a b = PSQ b a
instance (Ord p) => Poppable (PSQ' p) where
tryPop = fmap (first Q.key) . Q.minView
However this gives the error
Couldn't match type `Q.PSQ a p0' with `PSQ' p a'
even though they can match by setting p=p0.
(2) Type families won't work either.
type family PSQ' a b where
PSQ' b a = Q.PSQ a b
gives
Illegal type synonym family application in instance: PSQ' p
Now I could wrap PSQ with a newtype:
newtype PSQ'' a b = PSQ'' (Q.PSQ b a)
However this seems clunky to me because I have to constantly wrap/unwrap it. Is there an easier way?
Nope, not really. You could, of course, write your Poppable class to make it match PSQ. And if you like, you can generalize your newtype to
newtype Flip f a b = Flip (f b a)
at which point you could write
instance Poppable (Flip Q.PSQ a)
but none of this will get rid of the underlying annoyance factor. There are reasons Haskell doesn't support this (apparently, it makes inference much harder, sometimes impossible, etc.), so you'll just have to deal with it.
P.S., that type synonym may be more useful poly-kinded, with {-# LANGUAGE PolyKinds #-}, where it ends up meaning
newtype Flip (f :: k1 -> k2 -> *) (a :: k2) (b :: k1) = Flip (f b a)
You could simply abandon parametricity and use a type family to project whichever argument correspond to the 'element type':
class Poppable q where
type Elem q
tryPop :: q -> Maybe (Elem q, q)
data PSQ a p = ...
instance Ord p => Poppable (PSQ a p) where
type Elem (PSQ a p) = a
tryPop = ...
Note this is a more general formulation, but it may be harder to work with.
While using applicative functors in Haskell I've often run into situations where I end up with repetitive code like this:
instance Arbitrary MyType where
arbitrary = MyType <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
In this example I'd like to say:
instance Arbitrary MyType where
arbitrary = applyMany MyType 4 arbitrary
but I can't figure out how to make applyMany (or something similar to it). I can't even figure out what the type would be but it would take a data constructor, an Int (n), and a function to apply n times. This happens when creating instances for QuickCheck, SmallCheck, Data.Binary, Xml serialization, and other recursive situations.
So how could I define applyMany?
Check out derive. Any other good generics library should be able to do this as well; derive is just the one I am familiar with. For example:
{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH
import Test.QuickCheck
$( derive makeArbitrary ''MyType )
To address the question you actually asked, FUZxxl is right, this is not possible in plain vanilla Haskell. As you point out, it is not clear what its type should even be. It is possible with Template Haskell metaprogramming (not too pleasant). If you go that route, you should probably just use a generics library which has already done the hard research for you. I believe it is also possible using type-level naturals and typeclasses, but unfortunately such type-level solutions are usually difficult to abstract over. Conor McBride is working on that problem.
I think you can do it with OverlappingInstances hack:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies, OverlappingInstances #-}
import Test.QuickCheck
import Control.Applicative
class Arbitrable a b where
convert :: Gen a -> Gen b
instance (Arbitrary a, Arbitrable b c) => Arbitrable (a->b) c where
convert a = convert (a <*> arbitrary)
instance (a ~ b) => Arbitrable a b where
convert = id
-- Should work for any type with Arbitrary parameters
data MyType a b c d = MyType a b c d deriving (Show, Eq)
instance Arbitrary (MyType Char Int Double Bool) where
arbitrary = convert (pure MyType)
check = quickCheck ((\s -> s == s) :: (MyType Char Int Double Bool -> Bool))
Not satisfied with my other answer, I have come up with an awesomer one.
-- arb.hs
import Test.QuickCheck
import Control.Monad (liftM)
data SimpleType = SimpleType Int Char Bool String deriving(Show, Eq)
uncurry4 f (a,b,c,d) = f a b c d
instance Arbitrary SimpleType where
arbitrary = uncurry4 SimpleType `liftM` arbitrary
-- ^ this line is teh pwnzors.
-- Note how easily it can be adapted to other "simple" data types
ghci> :l arb.hs
[1 of 1] Compiling Main ( arb.hs, interpreted )
Ok, modules loaded: Main.
ghci> sample (arbitrary :: Gen SimpleType)
>>>a bunch of "Loading package" statements<<<
SimpleType 1 'B' False ""
SimpleType 0 '\n' True ""
SimpleType 0 '\186' False "\208! \227"
...
Lengthy explanation of how I figured this out
So here's how I got it. I was wondering, "well how is there already an Arbitrary instance for (Int, Int, Int, Int)? I'm sure no one wrote it, so it must be derived somehow. Sure enough, I found the following in the docs for instances of Arbitrary:
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => Arbitrary (a, b, c, d)
Well, if they already have that defined, then why not abuse it? Simple types that are merely composed of smaller Arbitrary data types are not much different than just a tuple.
So now I need to somehow transform the "arbitrary" method for the 4-tuple so that it works for my type. Uncurrying is probably involved.
Stop. Hoogle time!
(We can easily define our own uncurry4, so assume we already have this to operate with.)
I have a generator, arbitrary :: Gen (q,r,s,t) (where q,r,s,t are all instances of Arbitrary). But let's just say it's arbitrary :: Gen a. In other words, a represents (q,r,s,t). I have a function, uncurry4, which has type (q -> r -> s -> t -> b) -> (q,r,s,t) -> b. We are obviously going to apply uncurry4 to our SimpleType constructor. So uncurry4 SimpleType has type (q,r,s,t) -> SimpleType. Let's keep the return value generic, though, because Hoogle doesn't know about our SimpleType. So remembering our definition of a, we have essentially uncurry4 SimpleType :: a -> b.
So I've got a Gen a and a function a -> b. And I want a Gen b result. (Remember, for our situation, a is (q,r,s,t) and b is SimpleType). So I am looking for a function with this type signature: Gen a -> (a -> b) -> Gen b. Hoogling that, and knowing that Gen is an instance of Monad, I immediately recognize liftM as the monadical-magical solution to my problems.
Hoogle saves the day again. I knew there was probably some "lifting" combinator to get the desired result, but I honestly didn't think to use liftM (durrr!) until I hoogled the type signature.
Here is what I'v got at least:
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module ApplyMany where
import Control.Applicative
import TypeLevel.NaturalNumber -- from type-level-natural-number package
class GetVal a where
getVal :: a
class Applicative f => ApplyMany n f g where
type Res n g
app :: n -> f g -> f (Res n g)
instance Applicative f => ApplyMany Zero f g where
type Res Zero g = g
app _ fg = fg
instance
(Applicative f, GetVal (f a), ApplyMany n f g)
=> ApplyMany (SuccessorTo n) f (a -> g)
where
type Res (SuccessorTo n) (a -> g) = Res n g
app n fg = app (predecessorOf n) (fg<*>getVal)
Usage example:
import Test.QuickCheck
data MyType = MyType Char Int Bool deriving Show
instance Arbitrary a => GetVal (Gen a) where getVal = arbitrary
test3 = app n3 (pure MyType) :: Gen MyType
test2 = app n2 (pure MyType) :: Gen (Bool -> MyType)
test1 = app n1 (pure MyType) :: Gen (Int -> Bool -> MyType)
test0 = app n0 (pure MyType) :: Gen (Char -> Int -> Bool -> MyType)
Btw, I think this solution is not very useful in real world. Especially without local type-classes.
Check out liftA2 and liftA3. Also, you can easily write your own applyTwice or applyThrice methods like so:
applyTwice :: (a -> a -> b) -> a -> b
applyTwice f x = f x x
applyThrice :: (a -> a -> a -> b) -> a -> b
applyThrice f x = f x x x
There's no easy way I can see to get the generic applyMany you're asking for, but writing trivial helpers such as these is neither difficult nor uncommon.
[edit] So it turns out, you'd think something like this would work
liftA4 f a b c d = f <$> a <*> b <*> c <*> d
quadraApply f x = f x x x x
data MyType = MyType Int String Double Char
instance Arbitrary MyType where
arbitrary = (liftA4 MyType) `quadraApply` arbitrary
But it doesn't. (liftA4 MyType) has a type signature of (Applicative f) => f Int -> f String -> f Double -> f Char -> f MyType. This is incompatible with the first parameter of quadraApply, which has a type signature of (a -> a -> a -> a -> b) -> a -> b. It would only work for data structures that hold multiple values of the same Arbitrary type.
data FourOf a = FourOf a a a a
instance (Arbitrary a) => Arbitrary (FourOf a) where
arbitrary = (liftA4 FourOf) `quadraApply` arbitrary
ghci> sample (arbitrary :: Gen (FourOf Int))
Of course you could just do this if you had that situation
ghci> :l +Control.Monad
ghci> let uncurry4 f (a, b, c, d) = f a b c d
ghci> samples <- sample (arbitrary :: Gen (Int, Int, Int, Int))
ghci> forM_ samples (print . uncurry4 FourOf)
There might be some language pragma that can shoehorn the "arbitrary" function into the more diverse data types. But that's currently beyond my level of Haskell-fu.
This is not possible with Haskell. The problem is, that your function will have a type, that depends on the numeric argument. With a type system that allows dependent types, that should be possible, but I guess not in Haskell.
What you can try is using polymorphism and tyeclasses to archieve this, but it could become hacky and you need a big bunch of extensions to satisfy the compiler.
I find it extremely difficult to describe my problem, so here goes nothing:
I have a bunch of assertions on the type of a function. These assertions rely on a type variable that is not used for any parameter of the function, but is only used for internal bindings. Whenever I use this function it does not compile because, of course, the compiler has no information from which to guess what type to bind my type variable. Here is the code:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
TypeOperators, TypeSynonymInstances #-}
class C a a' where convert :: a -> a'
class F a b where apply :: a -> b
class S s a where select :: s -> a
data CInt = CInt Int
instance S (Int,String) Int where select (i,_) = i
instance F Int CInt where apply = CInt
f :: forall s a b . (S s a, F a b) => s -> b
f s =
let v = select s :: a
y = apply v :: b
in y
x :: Int
x = f (10,"Pippo")
And here is the generated error:
FunctorsProblems.hs:21:4:
No instances for (F a Int, S (t, [Char]) a)
arising from a use of `f' at FunctorsProblems.hs:21:4-17
Possible fix:
add an instance declaration for (F a Int, S (t, [Char]) a)
In the expression: f (10, "Pippo")
In the definition of `x': x = f (10, "Pippo")
Failed, modules loaded: none.
Prelude>
You are trying to intersect some set of instances of classes and for compiler there is no way to say that this intersection will be empty or single entry.
You want to force compiler to choose the right type for you without knowing which problems (information loss or complexity of calculations) that decision can bring in your program. If you want to do that you should give a hint to compiler what is the best type "a" for specific pair "s" and "b" (with us of that FunctionalDependencies you specified).
class E x a | x -> a
instance (S s Int, F Int CInt) => E (s, CInt) Int
f :: forall s a b . (E (s,b) a) => s -> b
Probably there is the way to specify order of preferred types of "a" for pair of "s" and "b" with further deduce of best "a" (i.e. use of type-level or something like that to attach that information).