I want to define a generic composition which works both for a -> b and for a -> Maybe b:
class Comp m where
(...) :: m a b -> m b c -> m a c
instance Comp (->) where
(...) = (>>>)
instance Comp (a -> Maybe b) where
(...) = (>=>)
Is it possible with all recent GHC extensions to define the second instance without a newtype wrapper similar to Control.Arrow.Kleisli?
Another problem is that the instances overlap, so for Just ... Just two equally sensible instances are possible. Is it possible to redesign ... so Just ... Just has polymorphic type so both a -> Maybe (Maybe a) and a -> Maybe a are valid typings for it?
If it's not possible maybe it's possible to defer implementation selection somehow. E.g.
data Comp a b = Comp a b
(...) = Comp
($$$) =
($$$) lifts generic compositions (which can be anything - not necessarily functions) to functions. Then Just ... Just $$$ (fromJust . fromJust)
This is probably not what you are looking for, but it will allow the instances to be defined. Explicit type annotations will often be required to select the appropriate instance. Using your example, Just ... Just is typed as Comp (->) a (Maybe a) b (Maybe b) => a -> Maybe b. FunctionalDependencies might help on cutting down when explicit type annotations are required, but would also restrict the possible instances to less than what you would like.
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Category
import Control.Monad
class Comp m a b b' c where
(...) :: m a b -> m b' c -> m a c
instance Comp (->) a b b c where
(...) = (>>>)
instance Monad m => Comp (->) a (m b) b (m c) where
(...) = (>=>)
Related
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)
Say I have a multi-param typeclass:
class B b => C a b | a -> b where
getB :: a -> (T, b)
Then I want a function:
f :: C a b => a -> c
f = g . getB
Which uses another function g :: B b => (T, b) -> c and getB, so an instance C a b is needed.
(Disclaimer: the real problem is much more complicated, the above-mentioned is only a simplified version.)
The problem is, given the functional dependency C a b | a -> b, we know that b can be completely decided by a, so theoretically I should be possible not to mention b in the type of f (since it is not used elsewhere but in instance C a b), but I didn't find any way to achieve this.
Also note that due to the existence of constraint B b in class C, I think I cannot use a TypeFamilies extension instead, for the syntax of that leaves nowhere for the type constraint B b to live.
So is there any way that I can hide the implementation details (the irrelevant type parameter b) from the user of this function f?
Using TypeFamilies, you could rewrite C into a single-parameter class as follows:
class B (BOf a) => C a where
type BOf a :: *
getB :: a -> (T, BOf a)
Which gives you the better looking constraint for f:
f :: C a => a -> c
There is (sadly) no way to omit parameters of a multi-parameter class to obtain a similar result.
If you turn on RankNTypes you can make a type alias that lets you elide b like this:
type C' a t = forall b. C a b => t
f :: C' a (a -> c)
f = g . getB
You can even include further contexts, if necessary, inside the second argument:
f' :: C' a ((Num a, Ord c) => a -> c)
f' = g . getB
This is pretty non-standard, though. You'll want to leave an explanatory comment... and the effort of writing it might be bigger, in the end, than the effort of just including a b at each use of C.
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)
While writing a class for a Collection/Container type (btw point me towards existing types if i'm reinventing the wheel) to provide a general interface for adding and removing elements from any 'Collection' type.
class (Eq (c a), Monoid (c a)) => Collection c a where
emptyColl :: c a -> Bool
splitColl :: c a -> (a, c a)
toColl :: a -> c a
size :: c a -> Int
combineColl :: a -> c a -> c a
(>|<) :: a -> c a -> c a
a >|< c = combineColl a c
I noticed instances of Collection could also be instances of Foldable. Using splitColl and emptyColl. So you don't need to write a Foldable as well, if you make constructs like this over several classes a significant amount of time, writing trivial instances, can be saved.
I tried to make Collection an instance of Foldable. However classes can't seem to be instantiated from other classes do they?
I received the following error messages:
instance Functor (Collection c) where
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘Collection c’ has kind ‘* -> GHC.Prim.Constraint’
In the instance declaration for ‘Functor (Collection c)’
instance Functor (Collection c a) where
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘Collection c a’ has kind ‘GHC.Prim.Constraint’
In the instance declaration for ‘Functor (Collection c a)’
How could I get the desired functionality? I think template Haskell might be the way to go here, I never used it tho, an example would be great :)
Thanks in advance!
PS: I've been writing haskell for about a year, minor tips that come to mind are much appreciated
The standard trick for this is to give implementations of the appropriate functions and let users write their own instances. For example, you might write
fmapColl :: (Collection c a, Collection c b) => (a -> b) -> c a -> c b
fmapColl f ca
| emptyColl ca = mkEmptyColl -- you don't have this in your class, but probably should
| otherwise = case splitColl ca of
(a, ca') -> f a >|< fmapColl f ca'
Assuming we had a suitable type class, say, CFunctor:
class CFunctor f where
type ConstraintI f
type ConstraintO f
cfmap :: (ConstraintI i, ConstraintO o) => (i -> o) -> f i -> f o
Then for a given Collection instance like Set we could instantiate CFunctor with minimal actual code like this:
instance CFunctor Set where
type ConstraintI Set = Ord
type ConstraintO Set = Ord
cfmap = fmapColl
You can see this pattern -- defining a "default" implementation for users to put in their instances -- in the base library's fmapDefault, for example.
The idea that the standard Monad class is flawed and that it should actually extend Functor or Pointed is floating around.
I'm not necessarily claiming that it is the right thing to do, but suppose that one was trying to do it:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
So far so good, but then when trying to use do-notation:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
The compiler complains:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Question:
Does do-notation work only for base:GHC.Base.Monad? Is there a way to make it work with an alternative Monad class?
Extra context:
What I really want to do is replace base:Control.Arrow.Arrow with a "generalized" Arrow class:
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
And then use the Arrow's proc-notation with my Arrow class, but that fails like in the example above of do-notation and Monad.
I'll use mostly Either as my pair type constructor and not the (,) type constructor as with the current Arrow class. This might allow to make the code of my toy RTS game (cabal install DefendTheKind) much prettier.
You need to use the NoImplicitPrelude extension for full rebindable syntax, including do and proc. In that case, you get the following, among other stuff:
"Do" notation is translated using whatever functions (>>=), (>>), and fail, are in scope (not the Prelude versions). List comprehensions, mdo (Section 7.3.6, “The recursive do-notation ”), and parallel array comprehensions, are unaffected.
You can also tweak some handling of negation, equality, literal values, and whatnot. Great way to obfuscate code!
p.s. -- If you're going to rebind the do syntax, what sigfpe calls "parameterized monads" are great fun. The same idea is available in category-extras under Control.Monad.Indexed. And yes, they do work with rebindable syntax, despite the wildly different type signatures!