The list monad is given here. Also see Spivak's paper here. So list is a monad. Is it a comonad? How would you prove that?
The list type constructor a ↦ μ L. 1 + a * L doesn't admit a comonad structure. Recall that if it were a comonad, we'd have (using the names from Haskell's Functor and Comonad typeclasses)
fmap :: ∀ a b. (a → b) → [a] → [b]
extract :: ∀ a. [a] → a
duplicate :: ∀ a. [a] → [[a]]
However, even without going into any required laws, extract cannot be implemented, since its input could be the empty list, giving no way to come up with an a.
The nonempty list type constructor a ↦ μ NE. a + a * NE does admit a comonad structure, with extract returning the first element, and duplicate mapping [x, y, ..., z] to [[x], [x, y], ..., [x, y, ..., z]] (note that each of them are non-empty by construction).
Related
I'm trying to turn a list of tuples into a single list with only the second value from each tuple.
targets :: [(a,b)] -> [a]
targets (x:xs) = [snd(x)] ++ targets xs
This is what I have so far but it is not working. Any help would be greatly appreciated.
There are two mistakes in your code. The first of which, GHC will warn you about:
<interactive>:3:30: error:
• Couldn't match type ‘a’ with ‘b’
‘a’ is a rigid type variable bound by
the type signature for:
targets :: forall a b. [(a, b)] -> [a]
at <interactive>:2:1-25
‘b’ is a rigid type variable bound by
the type signature for:
targets :: forall a b. [(a, b)] -> [a]
at <interactive>:2:1-25
Expected type: [b]
Actual type: [a]
The second element of the tuple is of type b (since you declare the tuple to be (a, b)), so the resulting array should not be [a] (what GHC calls the actual type), but it should be [b] (what GHC calls the expected type). Then, you're also missing a case. What if it's called on the empty array? Then it won't match (x:xs), so you should add a special case for that (also remember that every recursive function should have a base case):
targets :: [(a, b)] -> [b]
-- using x:y instead of [x] ++ y since they do the same thing
targets (x:xs) = snd x:targets xs
-- the base case for when nothing matches
targets _ = []
This is a mapping where for each 2-tuple, you take the second element, hence we can use map :: (a -> b) -> [a] -> [b]:
targets :: [(a,b)] -> [b]
targets = map snd
Notice that the return type is [b]: a list of bs, not as. Your type for a Graph however has as type [(Node a, [Int])], so you will need to concatenate these lists together.
A function that decides if a list begins with the letter ’a’ can be defined as follows:
test :: [Char] -> Bool
test ['a',_] = True
test _ = False
or
test :: [Char] -> Bool
test ('a':_) = True
test _ = False
Why does the first use [], while the second uses ()?
Does the second use ('a':_) to represent a tuple or a list?
If a tuple, doesn't test's argument have a list type [Char]?
If a list, doesn't () represent a tuple and how can it represent a list?
Does the second use ('a':_) to represent a tuple or a list?
A list.
If a list, doesn't () represent a tuple and how can it represent a list?
No, this is the unit type [wiki]. It is not a tuple, nor a list. Sometimes, as the Wikipedia article says, it is interpreted as an 0-tuple. It is defined in GHC.Tuple as well.
Why does the first use [], while the second uses ()?
The two are not equivalent. The former one matches a list with exactly two elements where the first element is an 'a', whereas the latter matches a list with at least one element where the first element is an 'a'. But the latter can match a list with one element, three elements, etc. whereas the former can only match lists with exactly two elements.
Background
(:) is a data constructor of a list. Indeed:
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
The ('a': _) is just a nicer form of ((:) 'a' _). We here thus use one of the list data constructors.
The ['a', _] is syntactical sugar for (:) 'a' ((:) _ []), so here we match a list that starts with an 'a' and where the tail is a list with as head a value we do not care about and its tail the empty list data constructor.
Haskell's list notation is just syntactic sugar for "cons"ing elements on to the empty list (that is, using the : operator).
In other words,
[x,y,z]
is syntactic sugar for
x:(y:(z:[]))
(although this form would more normally be written as x:y:z:[] without the parentheses, since : is right-associative).
So, in the example you quote, ('a':_) represents any list whose first element is 'a', while ['a',_] is sugar for (a:(_:[])) which is a list of length exactly 2, whose first element is a.
Note that tuples are something else entirely, being denoted by a sequence of values in parentheses separated by commas.
In Haskell there are data constructors that are symbols, some examples that may confuse you:
() :: ()
that's the type unit with its constructor () and its value ()
then there is:
(,) :: a -> b -> (a,b)
(,) is the constructor for tuples, for example (1,"b") that can be (1,) “b” or (,) 1 “b”
finally your case:
(:) :: a -> [a] -> [a]
for example, 1:[] that can be [1] or (:) 1 []
In OCaml, the inferred type of
let f = List.map fst
is
val f : ('_weak1 * '_weak2) list -> '_weak1 list = <fun>
while the inferred type of
let g x = List.map fst x
is
val g : ('a * 'b) list -> 'a list = <fun>
(types taken from utop).
As a result of this, f cannot be used polymorphically, while g can.
Why does this eta conversion between pure functions cause such a difference in type inference?
The difference is due to the value restriction, which does not allow the first definition to be polymorphic: it is defined by an application, which is not a value. The second form is defined as a function, which is a value. The notation '_weakN indicates a monomorphic type that is not yet resolved, as opposed to a polymorphic type variable like 'a.
See this chapter for more background.
Perhaps neither of these statements are categorically precise, but a monad is often defined as "a monoid in the category of endofunctors"; a Haskell Alternative is defined as "a monoid on applicative functors", where an applicative functor is a "strong lax monoidal functor". Now these two definitions sound pretty similar to the ignorant (me), but work out significantly differently. The neutral element for alternative has type f a and is thus "empty", and for monad has type a -> m a and thus has the sense "non-empty"; the operation for alternative has type f a -> f a -> f a, and the operation for monad has type (a -> f b) -> (b -> f c) -> (a -> f c). It seems to me that the real important detail is in the category of endofunctors versus over endofunctors, though perhaps the "strong lax" detail in alternative is important; but that's where I get confused because within Haskell at least, monads end up being alternatives: and I see that I do not yet have a precise categorical understanding of all the details here.
How can it be precisely expresseed what the difference is between alternative and monad, such that they are both monoids relating to endofunctors, and yet the one has an "empty" neutral and the other has a "non-empty" neutral element?
In general, a monoid is defined in a monoidal category, which is a category that defines some kind of (tensor) product of objects and a unit object.
Most importantly, the category of types is monoidal: the product of types a and b is just a type of pairs (a, b), and the unit type is ().
A monoid is then defined as an object m with two morphisms:
eta :: () -> m
mu :: (m, m) -> m
Notice that eta just picks an element of m, so it's equivalent to mempty, and curried mu becomes mappend of the usual Haskell Monoid class.
So that's a category of types and functions, but there is also a separate category of endofunctors and natural transformations. It's also a monoidal category. A tensor product of two functors is defined as their composition Compose f g, and unit is the identity functor Id. A monoid in that category is a monad. As before we pick an object m, but now it's an endofunctor; and two morphism, which now are natural transformations:
eta :: Id ~> m
mu :: Compose m m ~> m
In components, these two natural transformations become:
return :: a -> m a
join :: m (m a) -> m a
An applicative functor may also be defined as a monoid in the functor category, but with a more sophisticated tensor product called Day convolution. Or, equivalently, it can be defined as a functor that (laxly) preserves monoidal structure.
Alternative is a family of monoids in the category of types (not endofunctors). This family is generated by an applicative functor f. For every type a we have a monoid whose mempty is an element of f a and whose mappend maps pairs of f a to elements of f a. These polymorphic functions are called empty and <|>.
In particular, empty must be a polymorphic value, meaning one value per every type a. This is, for instance, possible for the list functor, where an empty list is polymorphic in a, or for Maybe with the polymorphic value Nothing. Notice that these are all polymorphic data types that have a constructor that doesn't depend on the type parameter. The intuition is that, if you think of a functor as a container, this constructor creates and empty container. An empty container is automatically polymorphic.
Both concepts are tied to the idea of a "monoidal category", which is a category you can define the concept of a monoid in (and certain other kinds of algebraic structures). You can think of monoidal categories as: a category defines an abstract notion of functions of one argument; a monoidal category defines an abstract notion of functions of zero arguments or multiple arguments.
A monad is a monoid in the category of endofunctors; in other words, it's a monoid where the product (a function of 2 arguments) and the identity (a function of 0 arguments) use the concept of multi-argument function defined by a particular (bizarre) monoidal category (the monoidal category of endofunctors and composition).
An applicative functor is a monoidal functor. In other words, it's a functor that preserves all the structure of a monoidal category, not just the part that makes it a category. It should be obvious that that means it has mapN functions for functions with any number of arguments, not just functions of one argument (like a normal functor has).
So a monad exists within a particular monoidal category (which happens to be a category of endofunctors), while an applicative functor maps between two monoidal categories (which happen to be the same category, hence it's a kind of endofunctor).
To supplement the other answers with some Haskell code, here is how we might represent the Day convolution monoidal structure #Bartosz Milewski refers to:
data Day f g a = forall x y. Day (x -> y -> a) (f x) (g y)
With the unit object being the functor Identity.
Then we can reformulate the applicative class as a monoid object with respect to this monoidal structure:
type f ~> g = forall x. f x -> g x
class Functor f => Applicative' f
where
dappend :: Day f f ~> f
dempty :: Identity ~> f
You might notice how this rhymes with other familiar monoid objects, such as:
class Functor f => Monad f
where
join :: Compose f f ~> f
return :: Identity ~> f
or:
class Monoid m
where
mappend :: (,) m m -> m
mempty :: () -> m
With some squinting, you might also be able to see how dappend is just a wrapped version of liftA2, and likewise dempty of pure.
I try to write a function, which takes a list of sublists, reverses sublists and returns concatenated, reversed sublists. Here is my attempt:
conrev :: Ord a => [[a]] -> [a]
conrev [[]] = []
conrev [[a]] = reverse [a]
conrev [(x:xs)] = reverse x ++ conrev [xs]
main = putStrLn (show (conrev [[1,2],[],[3,4]]))
I get this error:
3.hs:4:27:
Could not deduce (a ~ [a])
from the context (Ord a)
bound by the type signature for conrev :: Ord a => [[a]] -> [a]
at 3.hs:1:11-31
`a' is a rigid type variable bound by
the type signature for conrev :: Ord a => [[a]] -> [a] at 3.hs:1:11
In the first argument of `reverse', namely `x'
In the first argument of `(++)', namely `reverse x'
In the expression: reverse x ++ conrev [xs]
What am I doing wrong? The second question is - could the type signature be more generic? I have to write as generic as possible.
In the equation
conrev [(x:xs)] = reverse x ++ conrev [xs]
you match a list containing a single element, which is a nonempty list x:xs. So, given the type
conrev :: Ord a => [[a]] -> [a]
the list x:xs must have type [a], and thus x :: a.
Now, you call reverse x, which means x must be a list, x :: [b]. And then you concatenate
reverse x :: [b]
with
conrev [xs] :: [a]
from which it follows that b must be the same type as a. But it was determined earlier that a ~ [b]. So altogether, the equation demands a ~ [a].
If you had not written the (unnecessary) Ord a constraint, you would have gotten the less opaque
Couldn't construct infinite type a = [a]
error.
Your implementation would work if you removed some outer []:
conrev :: Ord a => [[a]] -> [a]
conrev [] = []
conrev [a] = reverse a
conrev (x:xs) = reverse x ++ conrev xs
but the better implementation would be
conrev = concat . map reverse
Your second pattern doesn't match what you want, it looks like you're mistaking the structure of the type for the structure of the value.
[[a]] as a type means "A list of lists of some type a"
[[a]] as a pattern means "Match a List containing a single list which contains a single element which will be bound to the name a.
Edit:
If I understand what you're trying to do the middle case is actually redundant. The third case will handle non-empty lists and the first case will handle empty lists. Making another case for the singleton list is unnecessary.
Edit 2:
There is a further problem with the implementation of the third case.
conrev :: Ord a => [[a]] -> [a]
conrev [(x:xs)] = reverse x ++ conrev [xs]
Given the type you see that x must be of type [a] and xs must be of type [[a]]. So writing conrev [xs] is passing a value of type [[[a]]] to conrev. This is where your type error is coming from. You're implicitly stating that [a] is the same type as a by calling convrev [xs].