Reify existential instance type parameter - haskell

I've got some code like this:
{-# LANGUAGE AllowAmbiguousTypes #-}
module Foo where
import Data.Proxy
class Foo x y
class Bar x y
class Baz x y
where
baz :: Proxy x -> Proxy y -> ()
instance (Foo a v, Bar b v) => Baz a b
where
baz _ _ = ()
instance Foo String String
instance Bar Int String
Now I actually want to use that Baz instance, so I write:
test :: Proxy String -> Proxy Int -> ()
test = baz
But of course there is an ambiguous "existential" v type parameter that I have not yet fixed to String (and there's no fundeps), so I get:
[typecheck] [E] /tmp/foo/src/Main.hs:20:8: error:
• Ambiguous type variable ‘v1’ arising from a use of ‘baz’
prevents the constraint ‘(Foo [Char] v1)’ from being solved.
Probable fix: use a type annotation to specify what ‘k1’,
‘v1’ should be.
These potential instance exist:
one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: baz
In an equation for ‘test’: test = baz
But how can I actually fix that type variable? I can't see a way to fix it using visible type application, because for example the following doesn't work:
test2 :: Proxy String -> Proxy Int -> ()
test2 = baz #String #Int #String -- is there some variation of this that would work?
I also can't see a way to use an explicit type annotation to fix that type parameter. Have I written an instance that is impossible to actually use?

It is indeed impossible to use that instance. When you call baz, you can supply a and b, but not v. v would have to be determined by some combination of superclass and instance constraints, and it is not.
You should be able to patch this up various places. Try either
instance s ~ String => Foo String s
or
instance s ~ String => Bar Int s
for example.

Related

Haskell type inference with GADTs and typeclass constraints on type variables

I defined a custom GADT where the type constructor has a type class constraint on the type variable, like this:
data MyGadt x where
Sample :: Show a => a -> MyGadt a
Now, if I define the following two functions:
foo (Sample a) = show a
bar a = Sample a
GHC infers types for them that are a bit irritating to me.
foo :: MyGadt x -> [Char] doesn't mention the Show constraint for x, while bar :: Show a => a -> MyGadt a does require the constraint to be mentioned explicitly.
I was assuming that I don't have to mention the constraint because it is declared in the GADT definition.
The only thing I can think of being part of the reason is the position of the GADT in the function. I'm not super deep into that but as far as I understand it, MyGadt is in positive position in foo and in negative position in bar.
When do I have to mention the type class constraints explicitly, and when does GHC figure it out itself based on the constraint on the GADTs type constructor?
It's the whole point of using a GADT that you want the constraint to show up in the signature of bar, instead of foo. If you don't want that, then you can use a plain old newtype instead:
newtype MyAdt = Sample a
foo :: Show a => MyAdt a -> String
foo (Sample a) = show a
bar :: a -> MyAdt a
bar = Sample
Having the constraint in neither foo nor bar clearly can't work, because then you would be able to e.g.
showFunction :: (Integer -> Integer) -> String
showFunction = foo . bar

Referring to type in instance declaration

I'm trying to use undefined to get value of type constant (something like sizeOf in storable).
module Main where
class MyClass a where
typeConst :: a -> String
-- ^ Argument is ignored
class TryRead a where
tryRead :: String -> Maybe a
newtype ByLen a = ByLen a
-- | Make all types under ByLen readable, if their typeConst's are longer then 3 characters
instance (Read a, MyClass a) => TryRead (ByLen a) where
tryRead = if len > 3
then Just . ByLen . read
else const Nothing
where
len = length $ typeConst (undefined :: a)
instance MyClass Int where
typeConst = const "moreThan3"
main :: IO ()
main = go (tryRead "214234" :: Maybe (ByLen Int))
where
go Nothing = print "Nothing :("
go (Just (ByLen i)) = print i
However, this gives an error:
Could not deduce (MyClass a0) arising from a use of ‘typeConst’
from the context (Read a, MyClass a)
bound by the instance declaration at src/Main.hs:13:10-49
The type variable ‘a0’ is ambiguous
Note: there is a potential instance available:
instance MyClass Int -- Defined at src/Main.hs:20:10
In the second argument of ‘($)’, namely
‘typeConst (undefined :: a)’
In the expression: length $ typeConst (undefined :: a)
In an equation for ‘len’: len = length $ typeConst (undefined :: a)
I don't understand what problem with type deducing is there, considering I specified type for typeConst argument explicitly as a type variable, which is bound by MyClass a, so it should in my mind have no problems applying to typeConst function.
You need ScopedTypeVaribales extension to be enabled for this to work either through a ghc flag -XScopedTypeVariables or through a pragma at the top of the file:
{-# LANGUAGE ScopedTypeVariables #-}
If it used within a class instance, nothing special needs to be done, because type variables from the head of the class are already in the scope, but if you would like to use it in simple top level function you will need an explicit forall in the type signature.

Resolving ambiguities for overloaded functions

I want to have an overloaded function in Haskell.
{-# LANGUAGE FlexibleInstances #-}
class Foo a where
foo :: a
instance Foo (String -> Int) where
foo = length
instance Foo String where
foo = "world"
However such overloading deals very poorly with type ambiguities. print $ foo "hello" would result in an error, while print $ length "hello" works fine. However, provided that my list of instances is fixed, there shouldn't be a technical reason why Haskell can't realize that the only instance of foo :: String -> a is foo :: String -> Int. Can I have Haskell make this realization?
It is easy to do in this particular case. Simply:
instance a ~ Int => Foo (String -> a) where foo = length
In your case GHCI knows, that foo :: String -> ??
We are going to change signature to String -> Int:
print (foo "hello" :: Int)

Type annotation in a typeclass' default value causes a "could not deduce" type error

This is a beginner's question, but I cannot recognize any answer to it anywhere.
The following code:
class A a where
foo :: a
class A a => B a where
bar :: a
bar = (foo :: a)
fails to compile in GHC, with the error message:
Could not deduce (A a1) arising from a use of `foo'
from the context (B a)
bound by the class declaration for `B'
...
GHC seems unconvinced that all the a's in the definition of typeclass B are the same. Can anyone please explain what exactly its line of reasoning is?
Removing the type annotation in line 5 avoids the problem of course, but I would still like to understand what is going on here...
You should indeed get rid of the type annotation. Type variables are not scoped in Haskell, so (foo :: a). Is interpreted as "have foo produce a value of type a for any type a", which cannot be done as foo will only produce values of those types a that are in the class A.
Put differently, your declaration of B is equivalent to
class A a => B a where
bar :: a
bar = (foo :: c)
That is, there is no connection between your use of the type variable a and the other uses in the declaration.
Dropping the explicit annotation solves your issue:
class A a => B a where
bar :: a
bar = foo
Now, the compiler can figure out for what type you want to invoke foo, i.e., for the type a that you wrote in the signature of bar and that appears in the head of the class declaration.
The Glasgow Haskell Compiler (GHC) comes with an extension that allows for scoped type variables. With that extension enabled, your fragment is type checked like you originally expected:
{-# LANGUAGE ScopedTypeVariables #-}
class A a where
foo :: a
class A a => B a where
bar :: a
bar = (foo :: a)
Prelude> :set -XScopedTypeVariables
Prelude> :{
Prelude| class A a where
Prelude| foo :: a
Prelude| class A a => B a where
Prelude| bar :: a
Prelude| bar = (foo :: a)
Prelude| :}
Prelude> :t bar
bar :: B a => a
Prelude>
but as dblhelox said, it's not really necessary to use scoped type variables here.

Inclusion of typeclasses with default implementation in Haskell

Consider the following definitions:
class Foo a where
foo :: a -> Int
class Bar a where
bar :: a -> [Int]
Now, how do I say "every Foo is also a Bar, with bar defined by default as bar x = [foo x]" in Haskell?
(Whatever I try, the compiler gives me "Illegal instance declaration" or "Constraint is no smaller than the instance head")
Btw, I can define my Foo and Bar classes in some other way, if this would help.
class Foo a where
foo :: a -> Int
-- 'a' belongs to 'Bar' only if it belongs to 'Foo' also
class Foo a => Bar a where
bar :: a -> [Int]
bar x = [foo x] -- yes, you can specify default implementation
instance Foo Char where
foo _ = 0
-- instance with default 'bar' implementation
instance Bar Char
As the automatic definition of a Bar instance through a Foo instance can lead to undecidable cases for the compiler - i.e. one explicit instance and one through Foo conflicting with each other - , we need some special options to allow the desired behaviour. The rest through is quite straigtforward.
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class Foo a where
foo :: a -> Int
class Bar a where
bar :: a -> [Int]
instance (Foo a) => Bar a where
bar x = [foo x]
Generally speaking you don't model things with type classes this way[*] - i.e. an instance of a type class should always be some concrete type, though that type itself can be parameteric - e.g. the Show instance for pair has this signature:
instance (Show a, Show b) => Show (a,b) where
Some of the approaches to "Generics" allow you to model a general base case and then have type specific exceptional cases. SYB3 allowed this - perhaps unfortunately SYB3 isn't the common practice Generics library it is Data.Data / Data.Generics which I think is SYB1.
[*] In the wild the story is a little more complicated - as Dario says UndecidableInstances can enable it.

Resources