map :: (a -> b) -> [a] -> [b]
fmap :: Functor f => (a -> b) -> f a -> f b
liftM :: Monad m => (a -> b) -> m a -> m b
Why do we have three different functions that do essentially the same thing?
map exists to simplify operations on lists and for historical reasons (see What's the point of map in Haskell, when there is fmap?).
You might ask why we need a separate map function. Why not just do away with the current
list-only map function, and rename fmap to map instead? Well, that’s a good question. The
usual argument is that someone just learning Haskell, when using map incorrectly, would much
rather see an error about lists than about Functors.
-- Typeclassopedia, page 20
fmap and liftM exist because monads were not automatically functors in Haskell:
The fact that we have both fmap and liftM is an
unfortunate consequence of the fact that the Monad type class does not require
a Functor instance, even though mathematically speaking, every monad is a
functor. However, fmap and liftM are essentially interchangeable, since it is
a bug (in a social rather than technical sense) for any type to be an instance
of Monad without also being an instance of Functor.
-- Typeclassopedia, page 33
Edit: agustuss's history of map and fmap:
That's not actually how it happens. What happened was that the type of map was generalized to cover Functor in Haskell 1.3. I.e., in Haskell 1.3 fmap was called map. This change was then reverted in Haskell 1.4 and fmap was introduced. The reason for this change was pedagogical; when teaching Haskell to beginners the very general type of map made error messages more difficult to understand. In my opinion this wasn't the right way to solve the problem.
-- What's the point of map in Haskell, when there is fmap?
Related
A few times now, I've found myself defining:
(<?>) :: [a] -> [a] -> [a]
[] <?> ys = ys
xs <?> _ = xs
This is an associative operation, of course, and the empty list [] is both left- and right-identity. It functions like Python's or.
It seems to me that this would make a nice (<|>), better than (++) would. Choosing the first nonempty list feels more like what I would expect from a typeclass named Alternative than concatenating lists. Admittedly, it doesn't fit MonadPlus as well, but I think that a small price to pay for salvation. We already have (++) and (<>) in the standard library; do we need another synonym, or would a new function (as far as I can tell) be more helpful?
I was at first thinking this might be a good Alternative instance for ZipList, but the discussion following this answer on the relevant question has convinced me otherwise. Other than backwards-compatibility and keeping MonadPlus sensible, what arguments are there for the current instance rather than this new one?
It is tricky to give your question a straight answer. Considered in isolation, there is nothing fundamentally wrong with your proposed instance. Still, there are quite a few things that can be said in support of the existing Alternative instance for lists.
Admittedly, it doesn't fit MonadPlus as well, but I think that a small price to pay for salvation.
One problem with going down that route is that Alternative is meant to capture the same general concept that MonadPlus does, but in terms of Applicative rather than Monad. To quote a relevant answer by Edward Kmett:
Effectively, Alternative is to Applicative what MonadPlus is to Monad.
From that point of view, having mismatching Alternative and MonadPlus instances is confusing and misleading, much like the analogous situation with Applicative and Monad instances would be.
(A possible counter to this argument would be wondering why do we need to care about MonadPlus anyway, given that it expresses the same concepts and offers essentially the same methods as Alternative. It should be noted, though, that the MonadPlus laws are stronger than the Alternative ones, as the relevant interactions of its methods with the Monad ones aren't expressible in terms of Alternative. That being so, MonadPlus still has meaning of its own, and a conceivable outcome of a hypothetical reform of the classes would be retaining it as a laws-only class, as discussed for instance in the final section of this answer by Antal Spector-Zabusky.)
Given such considerations, in what follows I will assume the continued relevance of MonadPlus. That makes writing the rest of this answer much easier, as MonadPlus is the original expression of the general concept in Haskell, and so it is pretty much necessary to refer to it while tracing the origin of the list instance of Alternative.
It seems to me that this would make a nice (<|>), better than (++) would. Choosing the first nonempty list feels more like what I would expect from a typeclass named Alternative than concatenating lists.
Tracing the roots of MonadPlus and Alternative, though, shows that the concatenating list instance is not just well-established, but even paradigmatic. For instance, quoting the classic paper by Hutton and Meijer, Monadic parsing in Haskell (1998), p. 4:
That is, a type constructor m is a member of the class MonadZero if it is a member of the class Monad, and if it is also equipped with a value zero of the specified type. In a similar way, the class MonadPlus builds upon the class MonadZero by adding a (++) operation of the specified type.
(Note that the authors do use (++) as their name for mplus.)
The notion mplus captures here is that of non-deterministic choice: if computations u and v each have some possible results, the possible results of u `mplus` v will be all of the possible results of u and v. The most elementary realisation of that is through MonadPlus for lists, though the idea extends to cover other non-determinism monads, such as Hutton and Meijer's Parser:
newtype Parser a = Parser (String -> [(a,String)])
To spin it another way, we might describe non-deterministic choice as inclusive disjunction, while the operation you propose is a form of (left-biased) exclusive choice. (It is worth noting that Hutton and Meijer also define (+++), a deterministic choice operator for their Parser which is rather like your operator except that it only picks the first result of the first successsful computation.)
A further relevant observation: one of the monad transformers from transformers that doesn't have a mtl class counterpart is ListT. That is so because the class which generalises the ListT functionality is precisely MonadPlus. Quoting a Gabriella Gonzalez comment:
MonadPlus is basically the "list monad" type class. For example: cons a as = return a `mplus` as and nil = mzero.
Note that the brokenness of transformers' ListT is not an issue. In general, the various formulations of ListT-done-right are equipped with a concatenating MonadPlus instance (examples: one, two, three).
So much for reasons why we might want to leave the Alternative [] and MonadPlus [] instances as they are. Still, this answer would be lacking if it didn't recognise that, as Will Ness reminds us, there are multiple reasonable notions of choice, and your operator embodies one of them.
The "official" laws (that is, the ones actually mentioned by the documentation) of Alternative and MonadPlus don't specify a single notion of choice. That being so, we end up with both non-deterministic (e.g. mplus #[]) and deterministic (e.g. mplus #Maybe) choice instances under the same Alternative/MonadPlus umbrella. Furthermore, if one chose to disregard my argument above and replace mplus #[] with your operator, nothing in the "official" laws would stop them. Over the years, there has been some talk of reforming MonadPlus by splitting it into classes with extra laws, in order to separate the different notions of choice. The odds of such a reform actually happening, though, don't seem high (lots of churn for relatively little practical benefit).
For the sake of contrast, it is interesting to consider the near-semiring interpretation, which is one of the reimaginings of MonadPlus and Alternative that might be invoked in a hypothetical class hierarchy reform. For a fully fleshed account of it, see Rivas, Jaskelioff and Schrijvers, A Unified View of Monadic and Applicative Non-determinism (2018). For our current purposes, it suffices to note the interpretation tailors the classes to non-deterministic choice by adding, to the monoid laws, "left zero" and "left distribution" laws for Alternative...
empty <*> x = empty
(f <|> g) <*> x = (f <*> x) <|> (g <*> x)
... as well as for MonadPlus:
mzero >>= k = mzero
(m1 `mplus` m2) >>= k = (m1 >>= k) `mplus` (m2 >>= k)
(Those MonadPlus laws are strictly stronger than their Alternative counterparts.)
In particular, your choice operator follows the purported Alternative left distribution law, but not the MonadPlus one. In that respect, it is similar to mplus #Maybe. MonadPlus left distribution makes it difficult (probably impossible, though I don't have a proof at hand right now) to drop any results in mplus, as we can't tell, on the right hand side of the law, whether m1 >>= k or m2 >>= k will fail without inspecting the results of m1 and m2. To conclude this answer with something tangible, here is a demonstration of this point:
-- Your operator.
(<?>) :: [a] -> [a] -> [a]
[] <?> ys = ys
xs <?> _ = xs
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = xs >>= \x -> if p x then [x] else []
-- If MonadPlus left distribution holds, then:
-- filter' p (xs `mplus` ys) = filter' p xs `mplus` filter' p ys
GHCi> filter' even ([1,3,5] <|> [0,2,4])
[0,2,4]
GHCi> filter' even [1,3,5] <|> filter' even [0,2,4]
[0,2,4]
GHCi> filter' even ([1,3,5] <?> [0,2,4])
[]
GHCi> filter' even [1,3,5] <?> filter' even [0,2,4]
[0,2,4]
I am trying to convince myself that the List monad (the one with flat lists, concatenation of lists and map element-wise) is not a free monad (to be precise, the free monad associated to some functor T). As far as I understand, I should be able to achieve that by
first finding a relation in the monad List between the usual operators fmap, join etc,
then showing that this relation does not hold in any free monad over a functor T, for all T.
What is a peculiar relation that holds in the List monad, that sets it apart from the free monads? How can I handle step2 if I don't know what T is? Is there some other strategy to show that flat lists are not free?
As a side note, to dispell any terminology clash, let me remark that the free monad associated to the pair functor is a tree monad (or a nested list monad), it is not the flat List monad.
Edit: for people acquainted with the haskell programming language, the question can be formulated as follows: how to show that there is no functor T such that List a = Free T a (for all T and up to monad isomorphism)?
(Adapted from my post in a different thread.)
Here is a full proof why the list monad is not free, including a bit of context.
Recall that we can construct, for any functor f, the free monad over f:
data Free f a = Pure a | Roll (f (Free f a))
Intuitively, Free f a is the type of f-shaped trees with leaves of type a.
The join operation merely grafts trees together and doesn't perform any
further computations. Values of the form (Roll _) shall be called
"nontrivial" in this posting. The task is to show that for no functor f, the monad Free f is isomorphic to the list monad.
The intuitive reason why this is true is because the
join operation of the list monad (concatenation) doesn't merely graft
expressions together, but flattens them.
More specifically, in the free monad over any functor, the result of binding a nontrivial
action with any function is always nontrivial, i.e.
(Roll _ >>= _) = Roll _
This can be checked directly from the definition of (>>=) for the free
monad.
If the list monad would be isomorphic-as-a-monad to the free monad over some
functor, the isomorphism would map only singleton lists [x] to values of
the form (Pure _) and all other lists to nontrivial values. This is
because monad isomorphisms have to commute with "return" and return x
is [x] in the list monad and Pure x in the free monad.
These two facts contradict each other, as can be seen with the following
example:
do
b <- [False,True] -- not of the form (return _)
if b
then return 47
else []
-- The result is the singleton list [47], so of the form (return _).
After applying a hypothetical isomorphism to the free monad over some
functor, we'd have that the binding of a nontrivial value (the image
of [False,True] under the isomorphism) with some function results in a
trivial value (the image of [47], i.e. return 47).
If you're okay with the free monad being applied to a type in particular which seems to be the case given the way you consider the Nat example given in the comments, then List can indeed be described using Free:
type List a = Free ((,) a) ()
The underlying idea here is that a List a is a Nat where each Suc node has been labelled with an a (hence the use of the (a,) functor rather than the Identity one).
Here is a small module witnessing the isomorphism together with an example:
module FreeList where
import Data.Function
import Control.Monad.Free
type List a = Free ((,) a) ()
toList :: [a] -> List a
toList = foldr (curry Free) (Pure ())
fromList :: List a -> [a]
fromList = iter (uncurry (:)) . fmap (const [])
append :: List a -> List a -> List a
append xs ys = xs >>= const ys
example :: [Integer]
example = fromList $ (append `on` toList) [1..5] [6..10]
I'm pretty new to haskell and don't get how to work with Maybe [a]. Normally I'm coding OOP (VB.NET) and in my free time I want to learn haskell (don't ask why ;) ).
So, what do I want to do? I want to read two files with numerical IDs and find out only the IDs that match in both files. Reading the files is not a big thing, it works wonderfully easy. Now, I get two lists of Maybe[Ids] (for a simple example, just think the IDs are Int). So the function I need looks like this
playWithMaybe :: (Maybe [a]) -> (Maybe [Int]) -> [Int]
Now I want to access list members as I used to like this
playWithMaybe (x:xs) (y:ys) = undefined
But unfortunately it's not allowed, GHC says for both lists
Couldn't match expected type ‘Maybe [Int]’ with actual type ‘[t0]’
So I played around a little bit but didn't find a way to access list members. Can someone help me out? A little bit of explanation would be a great thing!
To approach your problem from a different direction, I would argue you don't want a function that processes two Maybe [a]. Bear with me:
Fundamentally, the operation you want to do operates on two lists to give you a new list, eg,
yourFunction :: [a] -> [a] -> [a]
yourFunction a b = ...
That's fine, and you can and should write yourFunction as such. The fact that the data you have is Maybe [a] captures some additional, auxiliary information: the operation that created your input lists may have failed. The next step is to chain together yourFunction with the auxiliary information. This is exactly the purpose of do notation, to mix pure operations (like yourFunction) with contexts (the fact that the creation of one of your input lists may have failed):
playWithMaybe :: Maybe [a] -> Maybe [a] -> Maybe [a]
playWithMaybe maybeA maybeB =
do a <- maybeA -- if A is something, get it; otherwise, pass through Nothing
b <- maybeB -- if B is something, get it; otherwise, pass through Nothing
Just (yourFunction a b) -- both inputs succeeded! do the operation, and return the result
But then it turns out there are other kinds of contexts you might want to work with (a simple one, instead of Maybe that just captures "something bad happened", we can use Either to capture "something bad happened, and here is a description of what happened). Looking back at playWithMaybe, the "Maybe-ness" only shows up in one place, the Just in the last line. It turns out Haskell offers a generic function pure to wrap a pure value, like what we get from yourFunction, in a minimal context:
playWithMaybe' :: Maybe [a] -> Maybe [a] -> Maybe [a]
playWithMaybe' maybeA maybeB =
do a <- maybeA
b <- maybeB
pure (yourFunction a b)
But then Haskell also has a generic type to abstract the idea of a context, the Monad. This lets us make our function even more generic:
playWithMonad :: Monad m => m [a] -> m [a] -> m [a]
playWithMonad mA mB =
do a <- mA
b <- mB
pure (yourFunction a b)
Now we have something very generic, and it turns out it is so generic, it's already in the standard library! (This is getting quite subtle, so don't worry if it doesn't all make sense yet.)
import Control.Applicative
play :: Monad m => m [a] -> m [a] -> m [a]
play mA mB = liftA2 yourFunction mA mB
or even
import Control.Applicative
play' :: Monad m => m [a] -> m [a] -> m [a]
play' = liftA2 yourFunction
Why did I switch from Monad to Applicative suddenly? Applicative is similar to Monad, but even more generic, so given the choice, it is generally better to use Applicative if you can (similar to my choice to use pure instead of return earlier). For a more complete explanation, I strongly recommend Learn You a Haskell (http://learnyouahaskell.com/chapters), in particular chapters 11 and 12. Note- definitely read chapter 11 first! Monads only makes sense after you have a grasp on Functor and Applicative.
In general:
yourFunction Nothing Nothing = ...
yourFunction (Just xs) Nothing =
case xs of
[] -> ...
x':xs' -> ...
-- or separately:
yourFunction (Just []) Nothing = ...
yourFunction (Just (x:xs)) Nothing = ...
et cetera. Which cases need to be treated separately depends on the specific function. More likely you would combine functions working on Maybe with functions working on [].
If you want to "Just return an list with no elements" for Nothing, then you can write
maybeToList1 :: Maybe [a] -> [a]
maybeToList1 Nothing = []
maybeToList1 (Just xs) = xs
A better way to write the same function is maybeToList1 = maybe [] id (docs for maybe) or maybeToList1 = fromMaybe [], but since you are just starting you may want to come back to this one later.
Like others have said, [Int] and Maybe [Int] are not the same thing. Maybe [Int] includes the extra information that the list may or may not be there. You said that you read the Ids from files. Perhaps, the Maybe signifies whether the file existed or not, while the empty list signifies that the file did exist but contained no Ids.
If you want to work with the list, you first need to define what to do if there is no list. You can use this function to extract the list:
fromMaybe :: a -> Maybe a -> a
Maybe you want to treat having no list the same as having an empty list:
fromMaybe [] :: Maybe [a] -> [a]
Maybe you want to crash the entire program:
fromMaybe (error "Missing list") :: Maybe a -> a
There is also the more general maybe function, which you can use if the default value is not of the same type as what's contained in the Maybe:
maybe :: b -> (a -> b) -> Maybe a -> b
Both these functions are defined in the module Data.Maybe.
You can also just work with the lists as if they existed and worry about their existence later by using Applicative. You said you wanted to find the Ids common to both lists. You can do it like this:
maybeCommonIds :: Maybe [Int] -> Maybe [Int] -> Maybe [Int]
maybeCommonIds xs ys = intersect <$> xs <*> ys
intersect is defined in Data.List. Using maybeCommonIds will result in Maybe [Int]. The list contained inside will hold the common ids, but if either of the two lists did not exist, there is not list of common ids. In your case, this might be the same as having no common ids. In that case, you might want to pass the result to fromMaybe [], to get back the list.
I proved some theorems about lists, and extracted algorithms from them. Now I want to use heaps instead, because lookup and concatenation are faster. What I currently do to achieve this is to just use custom definitions for the extracted list type. I would like to do this in a more formal way, but ideally without having to redo all of my proofs. Lets say I have a type
Heap : Set -> Set
and an isomorphism
f : forall A, Heap A -> List A.
Furthermore, I have functions H_app and H_nth, such that
H_app (f a) (f b) = f (a ++ b)
and
H_nth (f a) = nth a
On the one hand, I would have to replace every list-recursion by a specialized function that mimics list recursion. On the other hand, beforehand I would want to replace ++ and nth by H_app and H_nth, so the extracted algorithms would be faster. The problem is that I use tactics like simpl and compute in some places, which will probably fail if I just replace everything in the proof code. It would be good to have a possibility to "overload" the functions afterwards.
Is something like this possible?
Edit: To clarify, a similar problem arises with numbers: I have some old proofs that use nat, but the numbers are getting too large. Using BinNat would be better, but is it possible to use BinNat instead of nat also in the old proofs without too much modification? (And especially, replace inefficient usages of + by the more efficient definition for BinNat?)
Just for the sake of clarity, I take it that Heap must look like
this:
Inductive Heap A : Type :=
| Node : Heap A -> A -> Heap A -> Heap A
| Leaf : Heap A.
with f being defined as
Fixpoint f A (h : Heap A) : list A :=
match h with
| Node h1 a h2 => f h1 ++ a :: f h2
| Leaf => []
end.
If this is the case, then f does not define an isomorphism between
Heap A and list A for all A. Instead, we can find a function
g : forall A, list A -> Heap A such that
forall A (l : list A), f (g l) = l
Nevertheless, we would like to say that both Heap and list are
equivalent in some sense when they are used to implement the same
abstraction, namely sets of elements of some type.
There is a precise and formal way in which we can validate this idea
in languages that have parametric polymorphism, such as Coq. This
principle, known as parametricity, roughly says that
parametrically polymorphic functions respect relations that we impose
on types we instantiate them with.
This is a little bit abstract, so let's try to make it more
concrete. Suppose that you have a function over lists (say, foo)
that uses only ++ and nth. To be able to replace foo by an
equivalent version on Heap using parametricity, we need to make
foo's definition polymorphic, abstracting over the functions over
lists:
Definition foo (T : Set -> Set)
(app : forall A, T A -> T A -> T A)
(nth : forall A, T A -> nat -> option A)
A (l : T A) : T A :=
(* ... *)
You would first prove properties of foo by instantiating it over
lists:
Definition list_foo := foo list #app #nth.
Lemma list_foo_lemma : (* Some statement *).
Now, because we now that H_app and H_nth are compatible with their
list counterparts, and because foo is polymorphic, the theory of
parametricity says that we can prove
Definition H_foo := foo Heap #H_app #H_nth.
Lemma foo_param : forall A (h : Heap A),
f (H_foo h) = list_foo (f h).
with this lemma in hand, it should be possible to transport properties
of list_foo to similar properties of H_foo. For instance, as a
trivial example, we can show that H_app is associative, up to
conversion to a list:
forall A (h1 h2 h3 : Heap A),
list_foo (H_app h1 (H_app h2 h3)) =
list_foo (H_app (H_app h1 h2) h3).
What's nice about parametricity is that it applies to any
parametrically polymorphic function: as long as appropriate
compatibility conditions hold of your types, it should be possible to
relate two instantiations of a given function in a similar fashion to
foo_param.
There are two problems, however. The first one is having to change
your base definitions to polymorphic ones, which is probably not so
bad. What's worse, though, is that even though parametricity ensures
that it is always possible to prove lemmas such as foo_param under
certain conditions, Coq does not give you that for free, and you still
need to show these lemmas by hand. There are two things that could help
alleviate your pain:
There's a parametricity plugin for Coq (CoqParam) which should
help deriving the boilerplate proofs for you automatically. I have
never used it, though, so I can't really say how easy it is to use.
The Coq Effective Algebra Library (or CoqEAL, for short) uses
parametricity to prove things about efficient algorithms while
reasoning over more convenient ones. In particular, they define
refinements that allow one to switch between nat and BinNat, as
you suggested. Internally, they use an infrastructure based on
type-class inference, which you could adapt to your original
example, but I heard that they are currently migrating their
implementation to use CoqParam instead.
A past paper problem asked me; to define a function p :: [a] -> [a] that swaps every two items in a list. Your function should swap the first with the second item, the third
with the fourth, and so on. define one by list comprehension another by recursion.
Well this is what I came up with:
import Test.QuickCheck
p :: [a] -> [a]
p [] = []
p xs = concat [ [y,x] | ((x,y),i) <- zip (zip xs (tail xs)) [1..], odd i]
q :: [a] -> [a]
q [] = []
q (x:y:zs) | even (length zs) = [y,x] ++ q zs
| otherwise = error "The list provided is not of even length"
prop_2 xs = even (length xs) ==> p xs == q xs
check2 = quickCheck prop_2
The functions work fine, but I wanted to check if the two are identical, so I put the quickCheck below; but this gives me an error for some reason saying
"ambiguous type variable [a0] arising from the use of prop_2"
I just don't understand what's wrong here, I looks perfectly sensible to me...
what exactly is Haskell complaining??
Let's start by commenting out check2 and asking GHCi what the type of prop_2 is:
*Main> :t prop_2
prop_2 :: Eq a => [a] -> Property
Ok, so the way you've written prop_2, it works for lists of any element type that is in the equality class.
Now, you want to pass prop_2 to the quickCheck function. Let's look at the type of quickCheck next:
*Main> :t quickCheck
quickCheck :: Testable prop => prop -> IO ()
This function actually has an immensely general type. It works on anything that's in the Testable class. So how does this Testable class work? There are a couple of base instances here, for example:
instance Testable Bool
instance Testable Property -- this is a simplification, but it's more or less true
These instances are defined in the QuickCheck library and tell you that you can quick-check
constant Booleans as well as elements of type Property.
Now, testing properties that do not depend on any inputs isn't particularly interesting. The interesting instance is this one:
instance (Arbitrary a, Show a, Testable prop) => Testable (a -> prop)
What this says is that if you know how to generate random values of a particular type (Arbitrary a) and how to show values of that type (Show a), then you can also test functions from that type a to an already testable type prop.
Why? Because that's how QuickCheck operates. In such a situation, QuickCheck will consult the Arbitrary instance in order to come up with random test cases of type a, apply the function to each of them, and check if the outcome is positive. If any of the tests fails, it will print a message informing you about the test failure, and it will print the test case (that's why there's a Show requirement, too).
Now, in our situation this means that we should be able to quick-check prop_2: it is a function that results in a Property. The important thing is that the function argument (of type [a] as long as Eq a holds) is a member of class Arbitrary and a member of class Show.
Here we arrive at the source of the error. The information available is not sufficient to make that conclusion. As I said in the beginning, prop_2 works for lists of any element type that admits equality. There's no built-in rule that says that all these type are in Arbitrary and Show. But even if there was, what kind of lists should QuickCheck generate? Should it generate lists of Booleans, lists of unit type, lists of functions, lists of characters, lists of integers? So many options, and the choice of element type may well affect whether you find a bug or not. (Consider that GHC would pick the unit type () with just one element. Then your property would hold for any two functions p and q that preserve the input lists' length, regardless of whether they have your desired swapping property or not.)
This is why you need to provide extra type information to GHC so that it can resolve which element type to use for the list. Doing so is simple enough. You can either annotate prop_2 itself:
prop_2 :: [Integer] -> Property
Or, if you don't want that (because you might want to run the tests on different kinds of lists without reimplementing prop_2), you can add a type annotation when calling quickCheck:
check2 = quickCheck (prop_2 :: [Integer] -> Property)
Now the code compiles, and we can run check2:
Main*> check2
+++ OK, passed 100 tests.