Functors don’t work with data types that require specific types - haskell

This works fine:
data Foo a = Foo a
instance Functor Foo where
fmap f (Foo s) = Foo (f s)
This throws an Error:
data Foo = Foo String
instance Functor Foo where
fmap f (Foo s) = Foo (f s)
Error:
Kind mis-match
The first argument of `Functor' should have kind `* -> *',
but `Foo' has kind `*'
In the instance declaration for `Functor Foo'
What am I missing here? Why can’t I use functors to wrap and unwrap Foo if it holds a specific type?
UPDATE
I guess I can ask this another way:
data Foo = Foo String deriving(Show)
let jack = Foo "Jack"
-- Some functory thingy here
putStrLn $ show $ tail <$> jack
-- Foo "ack"
Why can't I do this? Or is there another construct for this use case?

That's because Foo needs a single type variable to operate on.
The type of fmap is:
fmap :: Functor f => (a -> b) -> f a -> f b
Now try to specialize this for your Foo:
(a -> b) -> Foo -> Foo
Can you see where the problem is ? The types won't just match. So, to make Foo a functor, it has to be something like this:
Foo a
so that when you specialize it for fmap it has the following proper type:
(a -> b) -> Foo a -> Foo b

The type of fmap is generic; you can't constrain it:
fmap :: Functor f => (a -> b) -> f a -> f b
Those as and bs must be completely polymorphic (within the constraints of your Functor instance), or you don't have a Functor. The handwavy way of explaining why this is is because a Functor must obey some theoretical laws to make them play nice with Haskell's other data types:
fmap id = id
fmap (p . q) = (fmap p) . (fmap q)
If you have a data type that is parameterized over multiple types, i.e:
data Bar a b = Bar a b
You can write a Functor instance for Bar a:
instance Functor (Bar a) where
fmap f (Bar a b) = Bar a (f b)
You can also write a Bifunctor instance for Bar:
instance Bifunctor Foo where
first f (Bar a b) = Bar (f a) b
second f (Bar a b) = Bar a (f b)
...which again must follow some laws (listed on the linked page).
Edit:
You could write your own class to handle the type of behavior you're looking for, but it would look like this:
class FooFunctor f where
ffmap :: (String -> String) -> f -> f
But in this case, we'd have to make new entire classes for every single permutation of "inner types" we might have (like String), in order to cover all bases.
You can also write a class (call it Endo) that only permits endomorphisms (functions of type a -> a) on the "inner type" of a data type, like this:
class Endo f where
emap :: (a -> a) -> f a -> f a
Then, if you changed your data type a bit, and instantiated an appropriate instance of Endo, e.g.
data Foo' a = Foo' a
type Foo = Foo' String
instance Endo Foo' where
emap f (Foo a) = Foo (f a)
...if you write functions of type Foo -> Foo, you're guaranteed to preserve the "Stringiness" of the inner type you're mapping if you use emap. A quick search on hayoo reveals that this type of thing is relatively common practice, but doesn't really exist as a standard type class.

Coming from a dynamic language you probably see a Functor as a container of stuff and fmap as a way to transform things inside the container. However in Category theory a Functor can be seen as a way to transform a type into another type, and a way to transform a function on those type to function on the other type.
Imagine you have 2 differents worlds, one which is earth, and a virtual one when every body/things on earth has an avatar. The Functor is not the avatar but the magic wand which transforms everything to its avatar but also every single function of the real world into a function in the avatar world.
For example, with my magic wand I can transform a human to a frog (or a String to a list of Strings) but I can also transform the function "change the human hat" to change the frog hat" (or capitaize a String to capitalize all the String within a list).
fmap is the way you transform a function to another : you can see it as
a function which take 2 arguments - a function and a container - and apply this function to each element of this container
but also as a function which take 1 argmunt - a function - an return a function which takes a container and return a container.
The way you create a type from a type is less obvious In your first example you probably just see Foo String as new type, but you can also see Foo as a super function whic take the type String and return a new type : Foo String. That's what the * -> * kind is. Foo is not a type but a super function creating type from a type.
In your second example, Foo is not a type creator but just a simple type (kind : *), therefore it doesn't make sense to declare it as a functor.
If you really want to define fmap for the plain Foo in your 2nd example is to define a real functor and create a type alias for the plain type
data FooFunctor a = FooFunctor a
instance Functor Foofunctor where
fmap f (FooFunctor a) = FooFunctor (f a)
type Foo = FooFunctor String

A class that does pretty much exactly what you're asking for is MonoFunctor.
type instance Element Foo = String
instance MonoFunctor Foo where
fmap f (Foo s) = Foo (f s)

head "Jack" is not the string "J", but the character 'J'. So your own example shows why this does not work; head <$> jack would have to give Foo 'J', which is not a valid value of type Foo, since Foo can only be applied to String values, not Char values.
"Some other construct" for this use case is to define a "map" function for Foo, exactly as you're trying to define fmap. But that map function is not fmap, since it has to have type (String -> String) -> Foo -> Foo. So there's no need (or possibility) to make Foo an instance of Functor and name your mapping function fmap; the mapping function you want to use is simply not fmap.
Note that this means you cannot map arbitrary functions over your Foo values; only functions which take and return strings (so head is still out). Nor can you pass Foo values to generic functions that accept values in any functor; those functions might try to fmap functions over Foo that do not return strings; they're allowed to do this because they specified that they need functors, and that's exactly what defines a functor.

Related

How do you apply function constraints in instance methods in Haskell?

I'm learning how to use typeclasses in Haskell.
Consider the following implementation of a typeclass T with a type constrained class function f.
class T t where
f :: (Eq u) => t -> u
data T_Impl = T_Impl_Bool Bool | T_Impl_Int Int | T_Impl_Float Float
instance T T_Impl where
f (T_Impl_Bool x) = x
f (T_Impl_Int x) = x
f (T_Impl_Float x) = x
When I load this into GHCI 7.10.2, I get the following error:
Couldn't match expected type ‘u’ with actual type ‘Float’
‘u’ is a rigid type variable bound by
the type signature for f :: Eq u => T_Impl -> u
at generics.hs:6:5
Relevant bindings include
f :: T_Impl -> u (bound at generics.hs:6:5)
In the expression: x
In an equation for ‘f’: f (T_Impl_Float x) = x
What am I doing/understanding wrong? It seems reasonable to me that one would want to specialize a typeclass in an instance by providing an accompaning data constructor and function implementation. The part
Couldn't match expected type 'u' with actual type 'Float'
is especially confusing. Why does u not match Float if u only has the constraint that it must qualify as an Eq type (Floats do that afaik)?
The signature
f :: (Eq u) => t -> u
means that the caller can pick t and u as wanted, with the only burden of ensuring that u is of class Eq (and t of class T -- in class methods there's an implicit T t constraint).
It does not mean that the implementation can choose any u.
So, the caller can use f in any of these ways: (with t in class T)
f :: t -> Bool
f :: t -> Char
f :: t -> Int
...
The compiler is complaining that your implementation is not general enough to cover all these cases.
Couldn't match expected type ‘u’ with actual type ‘Float’
means "You gave me a Float, but you must provide a value of the general type u (where u will be chosen by the caller)"
Chi has already pointed out why your code doesn't compile. But it's not even that typeclasses are the problem; indeed, your example has only one instance, so it might just as well be a normal function rather than a class.
Fundamentally, the problem is that you're trying to do something like
foobar :: Show x => Either Int Bool -> x
foobar (Left x) = x
foobar (Right x) = x
This won't work. It tries to make foobar return a different type depending on the value you feed it at run-time. But in Haskell, all types must be 100% determined at compile-time. So this cannot work.
There are several things you can do, however.
First of all, you can do this:
foo :: Either Int Bool -> String
foo (Left x) = show x
foo (Right x) = show x
In other words, rather than return something showable, actually show it. That means the result type is always String. It means that which version of show gets called will vary at run-time, but that's fine. Code paths can vary at run-time, it's types which cannot.
Another thing you can do is this:
toInt :: Either Int Bool -> Maybe Int
toInt (Left x) = Just x
toInt (Right x) = Nothing
toBool :: Either Int Bool -> Maybe Bool
toBool (Left x) = Nothing
toBool (Right x) = Just x
Again, that works perfectly fine.
There are other things you can do; without knowing why you want this, it's difficult to suggest others.
As a side note, you want to stop thinking about this like it's object oriented programming. It isn't. It requires a new way of thinking. In particular, don't reach for a typeclass unless you really need one. (I realise this particular example may just be a learning exercise to learn about typeclasses of course...)
It's possible to do this:
class Eq u => T t u | t -> u where
f :: t -> u
You need FlexibleContextx+FunctionalDepencencies and MultiParamTypeClasses+FlexibleInstances on call-site. Or to eliminate class and to use data types instead like Gabriel shows here

Type synonyms with TemplateHaskell

If I have a type data Foo = Foo Int Int where frequently (but not always) the second parameter is a (fixed) function of the first, I could write a helper function mkFoo m = Foo m (f m) to reduce duplication.
I have this exact problem, but at the type level. The natural solution might be to use singletons to promote f, but my f isn't easily promoted. Instead, I'm trying to use TemplateHaskell and reflection to evaluate f at compile time at the data level. For example, I can currently do this (using ‑XDataKinds and GHC.TypeLits):
f :: Integer -> Integer
data Bar (a::Nat) (b::Nat)
mkNat :: Integer -> Q Type -- constructs a TypeLit
bar :: Bar 5 $(mkNat $ f $ proxy natValue (Proxy::Proxy 5))
It's obviously annoying to have to write this with a concrete type every time I want to use this pattern. Unfortunately, I know of no shorter or generic way to write the signature for bar. In particular, I can't define the type synonym
type Bar' (m :: Nat) = Bar m $(mkNat $ f $ proxy natVal (Proxy::Proxy m))
bar :: Bar' 5
due to TH stage restrictions (m is not imported or known when compiling the synonym).
Is there any way to simplify the signature of bar?

Does exporting type constructors make a difference?

Let's say I have an internal data type, T a, that is used in the signature of exported functions:
module A (f, g) where
newtype T a = MkT { unT :: (Int, a) }
deriving (Functor, Show, Read) -- for internal use
f :: a -> IO (T a)
f a = fmap (\i -> T (i, a)) randomIO
g :: T a -> a
g = snd . unT
What is the effect of not exporting the type constructor T? Does it prevent consumers from meddling with values of type T a? In other words, is there a difference between the export list (f, g) and (f, g, T()) here?
Prevented
The first thing a consumer will see is that the type doesn't appear in Haddock documentation. In the documentation for f and g, the type Twill not be hyperlinked like an exported type. This may prevent a casual reader from discovering T's class instances.
More importantly, a consumer cannot doing anything with T at the type level. Anything that requires writing a type will be impossible. For instance, a consumer cannot write new class instances involving T, or include T in a type family. (I don't think there's a way around this...)
At the value level, however, the main limitation is that a consumer cannot write a type annotation including T:
> :t (f . read) :: Read b => String -> IO (A.T b)
<interactive>:1:39: Not in scope: type constructor or class `A.T'
Not prevented
The restriction on type signatures is not as significant a limitation as it appears. The compiler can still infer such a type:
> :t f . read
f . read :: Read b => String -> IO (A.T b)
Any value expression within the inferrable subset of Haskell may therefore be expressed regardless of the availability of the type constructor T. If, like me, you're addicted to ScopedTypeVariables and extensive annotations, you may be a little surprised by the definition of unT' below.
Furthermore, because typeclass instances have global scope, a consumer can use any available class functions without additional limitation. Depending on the classes involved, this may allow significant manipulation of values of the unexposed type. With classes like Functor, a consumer can also freely manipulate type parameters, because there's an available function of type T a -> T b.
In the example of T, deriving Show of course exposes the "internal" Int, and gives a consumer enough information to hackishly implement unT:
-- :: (Show a, Read a) => T a -> (Int, a)
unT' = (read . strip . show') `asTypeOf` (mkPair . g)
where
strip = reverse . drop 1 . reverse . drop 9
-- :: T a -> String
show' = show `asTypeOf` (mkString . g)
mkPair :: t -> (Int, t)
mkPair = undefined
mkString :: t -> String
mkString = undefined
> :t unT'
unT' :: (Show b, Read b) => A.T b -> (Int, b)
> x <- f "x"
> unT' x
(-29353, "x")
Implementing mkT' with the Read instance is left as an exercise.
Deriving something like Generic will completely explode any idea of containment, but you'd probably expect that.
Prevented?
In the corners of Haskell where type signatures are necessary or where asTypeOf-style tricks don't work, I guess not exporting the type constructor could actually prevent a consumer from doing something they could with the export list (f, g, T()).
Recommendation
Export all type constructors that are used in the type of any value you export. Here, go ahead and include T() in your export list. Leaving it out doesn't accomplish anything other than muddying the documentation. If you want to expose an purely abstract immutable type, use a newtype with a hidden constructor and no class instances.

Why not a more general function than mappend in Haskell?

The mappend function is just a particular case of an associative operation where the two elements are of the same type. Why no packages propose an implementation of an associative function without that condition?
This would be pretty easy with the multi-parameters type classes extension:
{-# Language MultiParamTypeClasses #-}
module Append where
class Append a b where
(<->) :: a -> b -> a
Then, depending on the implementation of the instances, it would for example allow to concatenate an Int with a String:
"I am " <-> 42
> "I am 42"
or add optional parameter to data record types:
data MyType = MyType {_option :: Maybe String}
myType = MyType Nothing
myTypeWithOption = myType <-> "Hello!"
I have tried to search on Hoogle, Hayoo! and on the web but could not find such function.
So: a) does it exists? b) if not why?
There is a generalization (of sorts) of Monoid in base's Control.Category:
class Category cat where
id :: cat a a
(.) :: cat b c -> cat a b -> cat a c
It has the same laws as Monoid - in fact, the documentation explicitly says "id and (.) must form a monoid."
This isn't a true generalization, because it doesn't work with the same types. But associativity works exactly because of the restriction on the types it works with.
What you're describing is is an action of a monoid on a set. In Haskell this could be defined as
class Monoid m => MonoidAction m s where
act :: m -> s -> s
infixr 5 `act`
This is a left monoid action on s, you could also have a right action with the arguments reversed (as you have).
The action must be compatible with the monoid operations as follows:
a `act` (b `act` x) == (a <> b) `act` x
mempty `act` x == x
Another way how to view a monoid action and its laws is that Endo . act a homomorphism from monoid m to Endo s - the monoid of endomorphism on s.
Note that for every monoid you can define its action on itself by defining
instance Monoid m => MonoidAction m m where
act = mappend
See module Data.Monoid.Action.
You can't in general define associativity without the two arguments having the same type. If you try, it will not be type correct.

Type-class instances for types with 2 parameters when the type-class has only one

Consider the following type-class:
class Listable a where
asList :: a t -> [t]
It's easy enough to create instances for types with one parameter:
instance Listable [] where
asList = id
instance Listable Maybe where
asList (Just x) = [x]
asList Nothing = []
Now how would I make an instance for a pair with two identical type parameters? Of course I could do some wrapping:
data V2 a = V2 a a
v2 (p,q) = V2 p q
instance Listable V2 where
asList (V2 p q) = [p,q]
Now I could write things like asList $ v2 (47, 11), but this kind of defeats the purpose.
Is there a way to limit the type of pair to cases where both type parameters are equal, and to write a Listable instance for that? If not, what is the usual workaround?
There are lots of ways to do this, conceptually. Unfortunately, most of them don't actually work. Alas!
First, as a functional programmer, I'd wager that this is what you really want to write:
instance Listable (\a -> (a, a)) where
asList (p, q) = [p,q]
Unfortunately type-level lambdas don't exist. We could write a named version of the above lambda using a type synonym:
type Same2 f a = f a a
instance Listable (Same2 (,)) where { ... }
That's not allowed either, because the type synonym isn't fully-applied. We could instead imagine the type class taking an extra argument that would describe how to apply the type variables:
class Listable app f where
asList :: app f a -> [a]
instance Listable __ Maybe where { ... }
instance Listable __ (,) where { ... }
Without even thinking about what app might be, this also fails because we don't have a consistent kind for the f parameter.
Moving on to things that actually work, I think the most common way is to wrap the type synonym approach inside a newtype, then just deal with the wrapping and unwrapping that involves.
newtype Same2 f a = Same2 (f a a)
instance Listable (Same2 (,)) where { ... }
It's workable, if a bit ugly. You can also define type constructor composition and other toys this way, then go nuts with type-level points-free expressions buried under a pile of hoop-jumping boilerplate.
As a final approach, you can also encode the lambda-style approach above "in reverse", going from the fully-applied version, to the single type parameter:
class Listable t where
type ListableElem t :: *
asList :: t -> [ListableElem t]
Being able to do this sort of thing is one of the main motivations for type families. The same thing can be expressed with MPTCs and fundeps, but it's 1) equivalent and 2) much uglier, so I won't bother writing it out.
You have to define some wrapper type to do this. (You should use newtype however.) You might even define:
newtype Foo t a = Foo(t a a)
instance Listable (Foo (,)) where
asList (Foo (a,b)) = [a,b]

Resources