Haskell - All functions of form A -> A -> ... -> A - haskell

I have a type (call it A) and I want to make a typeclass of the functions of type A -> A, A -> A -> A, A -> A -> A -> ... etc. This doesn't work:
{-# LANGUAGE FlexibleInstances #-}
data A = A
class AsToA a where
takeA :: AsToA b => a -> A -> Either A b
instance AsToA (A -> A) where
takeA f a = Left (f a)
instance AsToA b => AsToA (A -> b) where
takeA f a = Right (f a)
I get the following error message:
AsToA.hs:12:22:
Couldn't match expected type ‘b1’ with actual type ‘b’
‘b’ is a rigid type variable bound by
the instance declaration at AsToA.hs:11:10
‘b1’ is a rigid type variable bound by
the type signature for
takeA :: AsToA b1 => (A -> b) -> A -> Either A b1
at AsToA.hs:12:3
Relevant bindings include
f :: A -> b (bound at AsToA.hs:12:9)
takeA :: (A -> b) -> A -> Either A b1 (bound at AsToA.hs:12:3)
In the first argument of ‘Right’, namely ‘(f a)’
In the expression: Right (f a)
Any ideas? Thanks very much for any advice.

There is some confusion between the two bs:
class AsToA a where
takeA :: AsToA b => a -> A -> Either A b
instance AsToA b => AsToA (A -> b) where
takeA f a = Right (f a)
These are not the same. Let's rename the first one to c
class AsToA a where
takeA :: AsToA c => a -> A -> Either A c
instance AsToA b => AsToA (A -> b) where
takeA f a = Right (f a)
Now, Right (f a) has type Either A b but should have type Either A c for any c such that AsToA c holds. This does not type check.
The issue here is that the signature
takeA :: AsToA c => a -> A -> Either A c
promises that takeA can return Either A c for any c, caller's choice. This is not what you want, I guess.
I'm still not sure about what the actual intended result is, but I guess the problem is similar to the following one.
Given a function f of type A->A->...->A return a function
\x -> f x x ..., with one application of
x for each -> in the type (hence of type A->A).
A possible solution is
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
data A = A -- could be anything
class C f where
takeA :: f -> A -> A
instance C (A -> A) where
takeA f = f
instance C b => C (A -> b) where
takeA f = \x -> takeA (f x) x
Note that this requires OverlappingInstances to be used, which is quite evil. I'd recommend to avoid it.
To avoid it, in this case it's enough to define an instance even for the
type A.
{-# LANGUAGE FlexibleInstances #-}
data A = A -- could be anything
class C f where
takeA :: f -> A -> A
instance C A where
takeA a = \_ -> a
instance C b => C (A -> b) where
takeA f = \x -> takeA (f x) x

As mentioned in the comments to the other answer, you might not really need the Either, and takeA is then basically always id, just with a type restriction. If so you can make this a method-less class:
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
data A = A
class AsToA a
takeA :: AsToA a => a -> a
takeA = id
instance AsToA (A -> A)
instance AsToA (A -> b) => AsToA (A -> (A -> b))
Alternatively, you might want to convert the functions to a common type that allows you to pass in As dynamically. If so Either won't be enough, but you can define your own:
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
data A = A
data R = Result A | MoreArgs (A -> R)
class AsToA a where
takeA :: a -> A -> R
instance AsToA (A -> A) where
takeA f a = Result (f a)
instance AsToA (A -> b) => AsToA (A -> (A -> b)) where
takeA f a = MoreArgs (takeA $ f a)

Related

Matching higher-kinded types in SYB

In general, I'm wondering if there's a way to write a generic fold that generalizes a function that applies a forall type like:
f :: forall a. Data (D a) => D a -> b
given some datatype D for which instance Data (D a) (possibly with constraints on a). To be concrete, consider something even as simple as False `mkQ` isJust, or generally, a query on the constructor of a higher-kinded datatype. Similarly, consider a transformation mkT (const Nothing) that only affects one particular higher-kinded type.
Without explicit type signatures, they fail with No instance for Typeable a0, which is probably the monomorphism restriction at work. Fair enough. However, if we add explicit type signatures:
t :: GenericT
t = mkT (const Nothing :: forall a. Data a => Maybe a -> Maybe a)
q :: GenericQ Bool
q = False `mkQ` (isJust :: forall a. Data a => Maybe a -> Bool)
instead we are told that the forall type of the outer signatures are ambiguous:
Could not deduce (Typeable a0)
arising from a use of ‘mkT’
from the context: Data a
bound by the type signature for:
t :: GenericT
The type variable ‘a0’ is ambiguous
I can't wrap my head around this. If I'm really understanding correctly that a0 is the variable in t :: forall a0. Data a0 => a0 -> a0, how is it any more ambiguous than in say mkT not? If anything, I would've expected mkT to complain because it is the one that interacts with isJust. Additionally, these functions are more polymorphic than the branching on concrete types.
I'm curious to know if this is a limitation of proving the inner constraint isJust :: Data a => ... — my understanding is that any type of instance Data inhabited with Maybe a must also have Data a to be valid by the instance constraint instance Data a => Data (Maybe a).
tldr: You need to create a different function.
mkT has the following signature:
mkT :: (Typeable a, Typeable b) => (a -> a) -> (b -> b)
And you want to apply it to a polymorphic function of type (forall x. Maybe x -> Maybe x). It is not possible: there is no way to instantiate a in (a -> a) to obtain (forall x. Maybe x -> Maybe x).
It's not just a limitation of the type system, the implementation of mkT wouldn't support such an instantiation either.
mkT simply compares concrete types a and b for equality at run time. But what you want is to be able to test whether b is equal to Maybe x for some x. The logic this requires is fundamentally more involved. But it is certainly still possible.
Below, mkT1 first matches the type b against the App pattern to know whether b is some type application g y, and then tests equality of g and f:
{-# LANGUAGE ScopedTypeVariables, RankNTypes, TypeApplications, GADTs #-}
import Type.Reflection
-- N.B.: You can add constraints on (f x), but you must do the same for b.
mkT1 :: forall f b. (Typeable f, Typeable b) => (forall x. f x -> f x) -> (b -> b)
mkT1 h =
case typeRep #b of
App g y ->
case eqTypeRep g (typeRep #f) of
Just HRefl -> h
_ -> id
_ -> id
Compilable example with mkQ1 as well:
{-# LANGUAGE ScopedTypeVariables, RankNTypes, TypeApplications, GADTs #-}
import Type.Reflection
mkT1 :: forall f b. (Typeable f, Typeable b) => (forall x. f x -> f x) -> (b -> b)
mkT1 h =
case typeRep #b of
App g y ->
case eqTypeRep g (typeRep #f) of
Just HRefl -> h
_ -> id
_ -> id
mkQ1 :: forall f b q. (Typeable f, Typeable b) => (forall x. f x -> q) -> (b -> q) -> (b -> q)
mkQ1 h =
case typeRep #b of
App g y ->
case eqTypeRep g (typeRep #f) of
Just HRefl -> const h
_ -> id
_ -> id
f :: Maybe x -> String
f _ = "matches"
main :: IO ()
main = do
print (mkQ1 f (\_ -> "doesn't match") (Just 3 :: Maybe Int)) -- matches
print (mkQ1 f (\_ -> "doesn't match") (3 :: Int)) -- doesn't match

The use of Forall in Haskell

Data.Constraint.Forall provides some quantification over constraints, however I fail to see how it can be used. Consider the following:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Forall where
import Prelude
import Data.Constraint.Forall
class Monoid (f a) => MonoidalFunctor f a
testfun :: Forall (MonoidalFunctor f) => (a -> f a) -> [a] -> f a
testfun = foldMap
testfun' :: Monoid (f a) => (a -> f a) -> [a] -> f a
testfun' = foldMap
I thought testfun would typecheck because Forall (MetaMonoid f) would work like forall a. Metamonoid f a, implying forall a. Monoid (f a) because of superclass constraint, but it doesn't.
Why does it not work and is there any workaround? I want to avoid having to write a lot of constraints like MyClass (f MyData) for different MyData types in my function where I know that any useful f will have instances for any f MyData anyway.
Use inst
inst :: forall p a. Forall p a :- p a
inst witness that, if you have forall a. p a, then you can set a to whatever you please and get p a out.
An entailment (:-) is
newtype a :- b = Sub (a => Dict b)
data Dict a = a => Dict
so, by pattern-matching on it, you can reveal the instance within it:
testfun :: forall f a. Forall (MonoidalFunctor f) => (a -> f a) -> [a] -> f a
testfun = case inst #(MonoidalFunctor f) #a of Sub Dict -> foldMap
(type applications/signatures necessary) or you can use (\\):
(\\) :: a => (b => r) -> a :- b -> r
testfun = foldMap \\ inst #(MonoidalFunctor f) #a
which reads "given that a is true and a value of r that also needs b to be true, followed by a value that can prove that b is true given a, make an r. If you rearrange a bit
(\\) :: (b => c) -> (a :- b) -> (a => c)
it looks quite a bit like function composition.
The reason for this dance is simply because it's beyond the reach of GHC to infer that Forall c means it can derive c a for any a; after all, that's why constraints exists. So, you have to be a bit more explicit about it.

Haskell: apply a polymorphic function twice

We can have a polymorphic function f :: a -> b implemented for different pairs of a and b. How can we make
twice :: (a -> b) -> a -> c
twice f x = f (f x)
type check? i.e. how can I write a function which applies a polymorphic function twice?
With Rank2Types we can get a bit closer but not quite there:
{-# LANGUAGE Rank2Types #-}
twice1 :: (forall a. a -> (m a)) -> b -> (m (m b))
twice1 f = f . f
twice2 :: (forall a. m a -> a) -> m (m b) -> b
twice2 f = f . f
so then some polymorphic functions can be applied twice:
\> twice1 (:[]) 1
[[1]]
\> twice2 head [[1]]
1
Can we go further?
The question was asked over Haskell cafe 10 years ago but wasn't quite answered (with type classes it becomes a lot of boilerplate).
{-# LANGUAGE TypeFamilies, RankNTypes, UnicodeSyntax #-}
type family Fundep a :: *
type instance Fundep Bool = Int
type instance Fundep Int = String
...
twice :: ∀ a . (∀ c . c -> Fundep c) -> a -> Fundep (Fundep a)
twice f = f . f
Now, that won't be much use actually because you can't define a (meaningful) polymorphic function that works with any c. One possibility is to toss in a class constraint, like
class Showy a where
type Fundep a :: *
showish :: a -> Fundep a
instance Showy Bool where
type Fundep Bool = Int
showish = fromEnum
instance Showy Int where
type Fundep Int = String
showish = show
twice :: ∀ a b . (Showy a, b ~ Fundep a, Showy b) =>
(∀ c . Showy c => c -> Fundep c) -> a -> Fundep b
twice f = f . f
main = print $ twice showish False
You can't make twice generic enough even in a dependently typed setting, but it's possible with intersection types:
twice :: (a -> b /\ b -> c) -> a -> c
twice f x = f (f x)
Now whenever f :: a -> b and f :: b -> c typecheck, twice will typecheck too.
There is also a beautiful spell in Benjamin Pierce's thesis (I changed the syntax slightly):
self : (A /\ A -> B) -> B
self f = f f
So self-application is typeable with intersection types as well.

Specify nested type variable constraints are of same instance in Haskell

The following which uses FooA explicitly as the type in (#) and in queryP compiles as expected:
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
module Foo where
class Foo a where
newtype FooParser a = FooParser { (#) :: FooA -> (a, FooA) }
queryP :: (FooA -> a) -> FooParser a
queryP f = FooParser $ \(b :: FooA) -> (f b, b)
data FooA = FooA Int
instance Foo FooA where
But when I try to define FooParser and queryP using the typeclass Foo like so:
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
module Foo where
class Foo a where
newtype FooParser a = FooParser { (#) :: Foo b => b -> (a, b) }
queryP :: Foo b => (b -> a) -> FooParser a
queryP f = FooParser $ \(b :: Foo b => b) -> (f b, b)
I get a could-not-deduce error:
Foo.hs:11:52:
Could not deduce (b ~ b1)
from the context (Foo b)
bound by the type signature for
queryP :: Foo b => (b -> a) -> FooParser a
at Foo.hs:10:11-42
or from (Foo b1)
bound by a type expected by the context: Foo b1 => b1 -> (a, b1)
at Foo.hs:11:12-53
‘b’ is a rigid type variable bound by
the type signature for queryP :: Foo b => (b -> a) -> FooParser a
at Foo.hs:10:11
‘b1’ is a rigid type variable bound by
a type expected by the context: Foo b1 => b1 -> (a, b1)
at Foo.hs:11:12
Relevant bindings include
b :: Foo b => b (bound at Foo.hs:11:26)
f :: b -> a (bound at Foo.hs:11:8)
queryP :: (b -> a) -> FooParser a (bound at Foo.hs:11:1)
In the expression: b
In the expression: (f b, b)
How can I specify that the b in the lambda function in queryP is of the same instance of the typeclass Foo as in the first parameter of f?
In the type definition
newtype FooParser a = FooParser { (#) :: Foo b => b -> (a, b) }
the type variable b is bound universially in a higher-rank type; i.e. the type of the newly introduced selector function (#) is
*Foo> :t (#)
(#) :: Foo b => FooParser a -> b -> (a, b)
But that means when you construct a FooParser a, the function you pass to the constructor must be typed at b -> (a, b) for any choice of b (as long as Foo b holds):
*Foo> :t FooParser
FooParser :: (forall b. Foo b => b -> (a, b)) -> FooParser a
However, in queryP you are given a function of type b -> a for some choice of b (the b is chosen by the caller, with the only restriction that Foo b will hold).
So if I set b ~ b1 and call queryP, that means I am passing you a function of type f :: b1 -> a. You then have to return to me a function of type forall b. (Foo b) => b -> (a, b) (wrapped in the constructor FooParser).
You can't just use f for this purpose, as for any choice of b other than b1 (e.g. b ~ b2) it will not be of the right type.
In its present form, you can basically only use functions from the Foo class and parametrically sufficiently polymorphic functions to construct your forall b. (Foo b) => b -> (a, b) function. Depending on what you are trying to do, you can either
Change queryP so that it takes a polymorphic function:
queryP :: (forall b. Foo b => (b -> a)) -> FooParser a
queryP f = FooParser $ \b -> (f b, b)
Change FooParser so that b is existentially bound:
{-# LANGUAGE ExistentialQuantification #-}
data FooParser a = forall b. Foo b => FooParser { (#) :: b -> (a, b) }
Note that these two changes mean (and imply) very different things.

Type Class Data Types

Having read the article Scrap your type classes, I re-implemented some of the ideas shown.
While doing that I came across something really strange: The Type Class - Type can be used as a type constraint! My question: Why is that?
My Code:
{-# LANGUAGE Rank2Types #-}
data IFunctor f = IFunctor {
_fmap :: forall a b. (a -> b) -> f a -> f b
}
-- this type checks...
_fmap2 :: IFunctor f => (a -> b) -> f (f a) -> f (f b)
_fmap2 = \inst -> _fmap inst . _fmap inst
In GHCi the following thing happens:
>>> :t _fmap2 :: IFunctor f => (a -> b) -> f (f a) -> f (f b)
_fmap2 :: IFunctor f => (a -> b) -> f (f a) -> f (f b)
:: IFunctor f -> (a -> b) -> f (f a) -> f (f b)
This doesn't work on GHC 7.8.2. It gives the error Expected a constraint, but ‘IFunctor f’ has kind ‘*’.
Older versions of GHC had a bug where they allowed => to be used like -> in certain situations. This is likely because internally type class constraints are passed as arguments in the form of method dictionaries.

Resources