Inclusion of typeclasses with default implementation in Haskell - 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.

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

Functor instance of kind *

I have newtype:
newtype Foo = Foo ([Int])
I would like to simply apply Int -> Int function over it like it is possible with fmap.
I thought it will be enough to derive or implement Functor instance, but it requires type of * -> * kind.
Is there some builtin way to make my type partially fmap-able?
https://hackage.haskell.org/package/mono-traversable-1.0.15.1/docs/Data-MonoTraversable.html#t:MonoFunctor
{-# LANGUAGE TypeFamilies #-}
type instance Element Foo = Int
instance MonoFunctor Foo where
-- omap :: (Int -> Int) -> Foo -> Foo
omap = ...
Before getting carried away, you should keep in mind that you're trying to avoid (1) naming and (2) writing the monomorphic function:
mapFoo :: (Int -> Int) -> (Foo -> Foo)
mapFoo f (Foo ints) = Foo (f <$> ints)
If you really don't want to give this function a separate name and want GHC to write the function for you, I think the only sensible way is to re-define your type as a proper functor of kind * -> * with an automatically derived instance:
newtype FooF a = Foo [a] deriving (Functor)
and then define a type alias for the specialization to Int:
type Foo = FooF Int
This is not precisely equivalent to your original definition of Foo. In particular, the following expression in isolation:
Foo [1,2,3]
will have type Num a => FooF a instead of type Foo = FooF Int, so GHC may fail to infer types in all the places it used to. But, this Foo type alias will mostly behave like your original Foo newtype and will allow you to write:
fmap (*5) $ Foo [1,2,3]
and such.
On the other hand, if you want to keep your newtype the same, don't mind writing the function yourself, yet don't want to give that function a separate name, you can't use fmap (at least not without overriding the prelude definition, which kind of defeats the purpose). However, as per #leftroundabout's answer, you can use omap from the mono-traversable package. Because this requires you to define the function yourself in a MonoFunctor Foo instance (e.g., using the same definition as mapFoo above), there's no real point unless you're doing this for a bunch of non-functors besides Foo and want to use a single omap name for all of them or want to write functions that can handle any such MonoFunctor uniformly.

How to handle functions of a multi-parameter typeclass, who not need every type of the typeclass?

I've defined a typeclass similar to an interface with a bunch of functions required for my program. Sadly, it needs multiple polymorphic types, but not every function of this multi-parameter typeclass needs every type. GHC haunts me with undeduceable types and i can't get the code running.
A reduced example:
{-# LANGUAGE MultiParamTypeClasses #-}
class Foo a b where
-- ...
bar :: a -> ()
baz :: Foo a b => a -> ()
baz = bar
GHC says
Possible fix: add a type signature that fixes these type variable(s)
How can I do this for b? Especially when I want to keep b polymorphic. Only an instance of Foo should define what this type is.
This is impossible.
The underlying problem is that a multiparameter type class depends on every type parameter. If a particular definition in the class doesn't use every type parameter, the compiler will never be able to know what instance you mean, and you'll never even be able to specify it. Consider the following example:
class Foo a b where
bar :: String -> IO a
instance Foo Int Char where
bar x = return $ read x
instance Foo Int () where
bar x = read <$> readFile x
Those two instances do entirely different things with their parameter. The only way the compiler has to select one of those instances is matching both type parameters. But there's no way to specify what the type parameter is. The class is just plain broken. There's no way to ever call the bar function, because you can never provide enough information for the compiler to resolve the class instance to use.
So why is the class definition not rejected by the compiler? Because you can sometimes make it work, with the FunctionalDependencies extension.
If a class has multiple parameters, but they're related, that information can sometimes be added to the definition of the class in a way that allows a class member to not use every type variable in the class's definition.
class Foo a b | a -> b where
bar :: String -> IO a
With that definition (which requires the FunctionalDependencies extension), you are telling the compiler that for any particular choice of a, there is only one valid choice of b. Attempting to even define both of the above instances would be a compile error.
Given that, the compiler knows that it can select the instance of Foo to use based only on the type a. In that case, bar can be called.
Splitting it in smaller typeclasses might be sufficient.
{-# LANGUAGE MultiParamTypeClasses #-}
class Fo a => Foo a b where
-- ...
foo :: a -> b -> ()
class Fo a where
bar :: a -> ()
baz :: Foo a b => a -> ()
baz = bar
Assuming you really want to use more than one instance for a given a (and so cannot use functional dependencies as others mentioned), one possibility which may or may not be right for you is to use a newtype tagged with a "phantom" type used only to guide type selection. This compiles:
{-# LANGUAGE MultiParamTypeClasses #-}
newtype Tagged t a = Tagged { unTagged :: a } -- Also defined in the tagged package
-- on Hackage
class Foo a b where
bar :: Tagged b a -> ()
baz :: Foo a b => Tagged b a -> ()
baz = bar
Then you will be able to wrap your values in such a way that you can give an explicit type annotation to select the right instance.
Another way of refactoring multi-parameter type classes when they get awkward is to use the TypeFamilies extension. Like FunctionalDependencies, this works well when you can reframe your class as having only a single parameter (or at least, fewer parameter), with the other types that are different from instance to instance being computed from the actual class parameters.
Generally I've found whenever I thought I needed a multi-parameter type class, the parameters almost always varied together rather than varying independently. In this situation it's much easier to pick one as "primary" and use some system for determining the others from it. Functional dependencies can do this as well as type families, but many find type families a lot easier to understand.
Here's an example:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
class Glue a where
type Glued a
glue :: a -> a -> Glued a
instance Glue Char where
type Glued Char = String
glue x y = [x, y]
instance Glue String where
type Glued String = String
glue x y = x ++ y
glueBothWays :: Glue a => a -> a -> (Glued a, Glued a)
glueBothWays x y = (glue x y, glue y x)
The above declares a class Glue of types that can be glued together with the glue operation, and that have a corresponding type which is the result of the "gluing".
I then declared a couple of instances; Glued Char is String, Glued String is also just String.
Finally I wrote a function to show how you use Glued when you're being polymorphic over the instance of Glue you're using; basically you "call" Glued as a function in your type signatures; this means glueBothWays doesn't "know" what type Glued a is, but it knows how it corresponds to a. You can even use Glued Char as a type, if you know you're gluing Chars but don't want to hard-code the assumption that Glued Char = String.

Haskell sub-typeclass requires UndecidableInstances?

Consider the following code example:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-} -- Is there a way to avoid this?
-- A generic class with a generic function.
class Foo a where
foo :: a -> a
-- A specific class with specific functions.
class Bar a where
bar :: a -> a
baz :: a -> a
-- Given the specific class functions, we can implement the generic class function.
instance Bar a => Foo a where
foo = bar . baz
-- So if a type belongs to the specific class...
instance Bar String where
bar = id
baz = id
-- We can invoke the generic function on it.
main :: IO ()
main =
putStrLn (foo "bar")
(My actual code is way more elaborate; this is a minimal boiled-down case to demonstrate the pattern.)
It isn't clear to me why UndecidableInstances are needed here - the type parameter a appears once in both sides of the Bar a => Foo a, so I expected things to "just work". I'm obviously missing something here. But at any rate, is there a way to do this without using UndecidableInstances?
There are a few approaches you can take; I don't think you've provided enough context to determine which would be the most appropriate. If you're using GHC-7.4, you might want to try the DefaultSignatures extension.
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DefaultSignatures #-}
-- A generic class with a generic function.
class Foo a where
foo :: a -> a
default foo :: Bar a => a -> a
foo = bar . baz
-- A specific class with specific functions.
class Bar a where
bar :: a -> a
baz :: a -> a
instance Bar String where
bar = id
baz = id
instance Foo String
main :: IO ()
main =
putStrLn (foo "bar")
You still need to declare that a type is an instance of Foo, but you don't need to repeat the method declaration because the default implementation will be used.
Another fairly lightweight approach is to use a newtype. If you have functions that need a Foo instance, you can wrap a Bar instance in the newtype.
newtype FooBar a = FooBar { unFooBar :: a }
instance Bar a => Foo (FooBar a) where
foo = FooBar . bar . baz . unFooBar
-- imported from a library or something...
needsFoo :: Foo a => a -> b
myFunc = needsFoo (FooBar someBar)
Alternatively, you may be able to get by with replacing foo with a normal function, or making a specialized version for Bar instances:
-- if every `Foo` is also a `Bar`, you can just do this. No need for `Foo` at all!
foo :: Bar a => a -> a
foo = bar . baz
-- if most `Foo`s aren't `Bar`s, you may be able to use this function when you have a `Bar`
fooBar :: Bar a => a -> a
foo = bar . baz
These are probably the best solutions if they work for your situation.
Another option is to declare every Foo instance manually. Although there may be a lot of different conceivable instances, it's fairly common for codebases to only have a handful of instances that are actually used. If that's true here, it's probably less work to just write out the 3 or 4 instances you need rather than try to implement a more general solution.
As a very last resort, you can use something like your original code, but you'll also need OverlappingInstances to make it work (if you don't need OverlappingInstances, then you don't need a Foo class). This is the extension that allows GHC to choose the "most specific instance" when there are multiple available matches. This will more or less work, although you may not get what you expect.
class Foo a where
foo :: a -> a
class Bar a where
bar :: a -> a
baz :: a -> a
instance Bar String where
bar = id
baz = id
instance Bar a => Foo a where
foo = bar . baz
instance Foo [a] where
foo _ = []
main :: IO ()
main =
print (foo "foo")
Now main prints an empty string. There are two Foo instances, for a and [a]. The latter is more specific, so it gets chosen for foo "foo" since a string has type [Char], although you probably wanted the former. So now you'd also need to write
instance Foo String where
foo = bar . baz
at which point you may as well leave out the Bar a => Foo a instance entirely.
In addition to answer above. Politics used in Data.Traversable module from base library is attractive. In short, giving generic instance in library forces end user to accept your decision, and this is not always the best thing to do. Data.Traversable contains functions like foldMapDefault, which gives default implementation, but decision of specific implementation is still up to user.

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.

Resources