Source code definition of `==` for lists in Haskell - list

Does anyone know how exactly == is defined for lists in Haskell? I've tried Hoogling it but can't seem to find where the instance Eq [a] is defined.

The GHC implementation of Eq and other built-in instances is written in GHC.Classes. Specifically, you're looking for Eq [a]
instance (Eq a) => Eq [a] where
{-# SPECIALISE instance Eq [[Char]] #-}
{-# SPECIALISE instance Eq [Char] #-}
{-# SPECIALISE instance Eq [Int] #-}
[] == [] = True
(x:xs) == (y:ys) = x == y && xs == ys
_xs == _ys = False
Nothing super exciting. Two empty lists are equal, and two nonempty lists are equal if the heads and tails are equal. Finally, two arbitrary lists are non-equal. The only interesting part is the specialization directives, which should monomorphize equality checks on integer lists, strings, and lists of strings.

Related

nub not compiling when checking a list for duplicates

Working on a sudoku inspired assignment and I need to implement a function that checks if a Block Cell has no repeated elements in it (to check if its a valid solution to the puzzle).
okBlock :: Block Cell -> Bool
okBlock b = okList $ filter (/= Nothing) b
where
okList :: [a]-> Bool
okList list
| (length list) == (length (nub list)) = True
| otherwise = False
Block a = [a]
Cell = [Maybe Int]
Haskell complains saying No instance for (Eq a) arising from a use of "==" Possible fix: add (Eq a) to the context of the type signature for okList...
Adding Eq a to the type signature does not help. I have tried the function in the terminal and it works fine for for lists, and for lists of lists (i.e the type I am feeding it in the function).
What am I missing here?
Well you can only filter out duplicates, if there is a way to check whether two values are duplicates. If we look at the type signature for nub, we see:
nub :: Eq a => [a] -> [a]
So that means that in order to filter out duplicates in a list of as, we need a to be an instance of the Eq class. We can thus simply forward the type constraint further in the signatures of the functions:
okBlock :: Block Cell -> Bool
okBlock b = okList $ filter (/= Nothing) b
where
okList :: Eq => [a] -> Bool
okList list
| (length list) == (length (nub list)) = True
| otherwise = False
We do not need to specify that Cell is an instance of Eq because:
Int is an instance of Eq;
if a is an instance of Eq, so is Maybe a, so Maybe Int is an instance of Eq; and
if a is an instance of Eq, so is [a], so [Maybe Int] is an instance of Eq.
That being said we can do some syntactical improvements of the code:
there is no need to work with guards if you simply return the result of the guard True and False, and
you can use an eta reduction and omit the b in okBlock.
you don't need parentheses around function application (unless to feed to result straight to another, non-infix function).
This gives us:
okBlock :: Block Cell -> Bool
okBlock = okList . filter (/= Nothing)
where
okList :: Eq => [a] -> Bool
okList list = length list == length (nub list)
A final note is that usually you do not have to specify a type signature. In that case Haskell will aim to dervice the most generic type signature. So you can write:
okBlock = okList . filter (/= Nothing)
where
okList list = length list == length (nub list)
Now okBlock will have type:
Prelude Data.List> :t okBlock
okBlock :: Eq a => [Maybe a] -> Bool
Three points that are too big to make in a comment.
nub is horribly slow
nub takes O(n^2) time to process a list of length n. Unless you know the list is very short, this is the wrong function to use to remove duplicates from a list. Adding a bit more information about what sort of thing you're working with allows more efficient nubbing. The simplest, and probably most general, approach that isn't absolutely wretched is to use an Ord constraint:
import qualified Data.Set as S
nubOrd :: Ord a => [a] -> [a]
nubOrd = go S.empty where
go _seen [] = []
go seen (a : as)
| a `S.member` seen = go seen as
| otherwise = go (S.insert a seen) as
length is wasteful
Suppose I write
sameLength :: [a] -> [b] -> Bool
sameLength xs ys = length xs == length ys
(which uses the approach you did). Now imagine I calculate
sameLength [1..16] [1..2^100]
How long will that take? Calculating length [1..16] will take nanoseconds. Calculating length [1..2^100] will probably take billions of years using current hardware. Whoops. What's the right way? Pattern match!
sameLength [] [] = True
sameLength (_ : xs) (_ : ys) = sameLength xs ys
sameLength _ _ = False
Nubbing isn't the right solution to this problem
Suppose I ask noDuplicates (1 : [1,2..]). Obviously, there's a duplicate, right at the beginning. But if I use sameLength and nub to check, I will never get an answer. It will keep building the nubbed list and comparing it to the original list until the seen becomes so large it exhausts your computer's memory. How can you fix that? By directly calculating what you need:
noDuplicates = go S.empty where
go _seen [] = True
go seen (x : xs)
| x `S.member` seen = False
| otherwise = go (S.insert x seen) xs
Now the program will conclude that there's a duplicate the moment it sees the second 1.

Duplicates removal with foldl

I'm trying to write my implementation of remdps, function, which removes nearest duplicates in a list. For example: "aaabbbsscaa" should became "absca". I have to use foldl. Here is my attempt:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if tail newlist /= ele then newlist:ele
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
And the error:
4.hs:4:41:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(/=)', namely `ele'
In the expression: tail newlist /= ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:50:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the first argument of `(:)', namely `newlist'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:58:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(:)', namely `ele'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
fish: Unknown command './4'
ghc 4.hs; and ./4
The question is always the same:). What's wrong?
//edit
OK, I have a working code. It uses reverse and ++, so it's very ugly:).
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if head (reverse newlist) /= ele then newlist ++ [ele]
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
What you're probably trying to do is this:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if last newlist /= ele then newlist ++ [ele]
else newlist
The changes:
: works only in one way: on the left is the head of the list (type a), on the right the tail (type [a]). It's sometimes also called "cons". What you want to do is called "snoc": on its right is the last element of the list (type a), and on the left the initial part (type [a]).
"snoc" doesn't exist in the Prelude, so instead, you just write it in a different way: newlist ++ [ele]. (Compare this to x : xs == [x] ++ xs.)
tail newlist == ele becomes last newlist == ele. tail gets the list without its head, but you want to compare the last element of newlist. For that purpose, you have last. (By the way, to get the initial part of a list, you can use init.)
Note that you've also swapped the branches of your if-statement, leaving you with aaa as the answer. -edit- I see that you've updated that now ;)
Also note that this is a very slow approach. Every "snoc" and last will take longer as the answer of remdps grows, because Prelude lists are much better at "cons" and head. Try rewriting the function so that it uses "cons" instead. Hint: you'll need reverse at some point.
Furthermore, this function will not work when used with infinite lists, because of the way foldl works. It might be an interesting exercise to rewrite this function to use foldr instead.
The type annotation of helper suggest that ele is of type a
And you do the following test (tail(newlist) == ele), but tail if of type [a]
You cannot compare two value if different type.
This is not the only error.
I suggest you take a look at the docs for Data.List. Specifically for tail you'll see that the type is [a] -> [a], so obviously it doesn't return the last element of the list as one might think.
If you're looking to get a single element of out of a list (the last one) you need something with type [a] -> a. The power of haskell comes from the fact that this information is almost enough to find the right function.
Just Hoogle it!
P.S. As a side note - this approach is quite slow, as mentioned in Tinctorius' answer
To expand on my second comment, though this doesn't answer your question as posed, I would very much not use foldl to do this. Back in my Scheme days I'd solve it with this pet kfoldr function of mine, which I've translated to Haskell here:
-- | A special fold that gives you both left and right context at each right
-- fold step. See the example below.
kfoldr :: (l -> a -> l) -> l -> (l -> a -> r -> r) -> (l -> r) -> [a] -> r
kfoldr advance left combine seedRight [] = seedRight left
kfoldr advance left combine seedRight (x:xs) = combine left x (subfold xs)
where subfold = let newLeft = advance left x
in newLeft `seq` kfoldr advance newLeft combine seedRight
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = kfoldr advance Nothing step (const [])
where
-- advance is the left context generator, which in this case just
-- produces the previous element at each position.
advance _ x = Just x
-- step's three arguments in this case are:
-- (a) the element to the left of current
-- (b) the current element
-- (c) the solution for the rest of the list
step Nothing x xs = x:xs
step (Just x') x xs
| x == x' = xs
| otherwise = x:xs
Haskell's Data.List library has mapAccumL and mapAccumR which are similar but they map instead of folding. There's also the intimately related scanl and scanr, which can probably be used to implement kfoldr (but I haven't bothered to try).

Lists defined as Maybe in Haskell? Why not?

You don't offen see Maybe List except for error-handling for example, because lists are a bit Maybe themselves: they have their own "Nothing": [] and their own "Just": (:).
I wrote a list type using Maybe and functions to convert standard and to "experimental" lists. toStd . toExp == id.
data List a = List a (Maybe (List a))
deriving (Eq, Show, Read)
toExp [] = Nothing
toExp (x:xs) = Just (List x (toExp xs))
toStd Nothing = []
toStd (Just (List x xs)) = x : (toStd xs)
What do you think about it, as an attempt to reduce repetition, to generalize?
Trees too could be defined using these lists:
type Tree a = List (Tree a, Tree a)
I haven't tested this last piece of code, though.
All ADTs are isomorphic (almost--see end) to some combination of (,),Either,(),(->),Void and Mu where
data Void --using empty data decls or
newtype Void = Void Void
and Mu computes the fixpoint of a functor
newtype Mu f = Mu (f (Mu f))
so for example
data [a] = [] | (a:[a])
is the same as
data [a] = Mu (ListF a)
data ListF a f = End | Pair a f
which itself is isomorphic to
newtype ListF a f = ListF (Either () (a,f))
since
data Maybe a = Nothing | Just a
is isomorphic to
newtype Maybe a = Maybe (Either () a)
you have
newtype ListF a f = ListF (Maybe (a,f))
which can be inlined in the mu to
data List a = List (Maybe (a,List a))
and your definition
data List a = List a (Maybe (List a))
is just the unfolding of the Mu and elimination of the outer Maybe (corresponding to non-empty lists)
and you are done...
a couple of things
Using custom ADTs increases clarity and type safety
This universality is useful: see GHC.Generic
Okay, I said almost isomorphic. It is not exactly, namely
hmm = List (Just undefined)
has no equivalent value in the [a] = [] | (a:[a]) definition of lists. This is because Haskell data types are coinductive, and has been a point of criticism of the lazy evaluation model. You can get around these problems by only using strict sums and products (and call by value functions), and adding a special "Lazy" data constructor
data SPair a b = SPair !a !b
data SEither a b = SLeft !a | SRight !b
data Lazy a = Lazy a --Note, this has no obvious encoding in Pure CBV languages,
--although Laza a = (() -> a) is semantically correct,
--it is strictly less efficient than Haskell's CB-Need
and then all the isomorphisms can be faithfully encoded.
You can define lists in a bunch of ways in Haskell. For example, as functions:
{-# LANGUAGE RankNTypes #-}
newtype List a = List { runList :: forall b. (a -> b -> b) -> b -> b }
nil :: List a
nil = List (\_ z -> z )
cons :: a -> List a -> List a
cons x xs = List (\f z -> f x (runList xs f z))
isNil :: List a -> Bool
isNil xs = runList xs (\x xs -> False) True
head :: List a -> a
head xs = runList xs (\x xs -> x) (error "empty list")
tail :: List a -> List a
tail xs | isNil xs = error "empty list"
tail xs = fst (runList xs go (nil, nil))
where go x (xs, xs') = (xs', cons x xs)
foldr :: (a -> b -> b) -> b -> List a -> b
foldr f z xs = runList xs f z
The trick to this implementation is that lists are being represented as functions that execute a fold over the elements of the list:
fromNative :: [a] -> List a
fromNative xs = List (\f z -> foldr f z xs)
toNative :: List a -> [a]
toNative xs = runList xs (:) []
In any case, what really matters is the contract (or laws) that the type and its operations follow, and the performance of implementation. Basically, any implementation that fulfills the contract will give you correct programs, and faster implementations will give you faster programs.
What is the contract of lists? Well, I'm not going to express it in complete detail, but lists obey statements like these:
head (x:xs) == x
tail (x:xs) == xs
[] == []
[] /= x:xs
If xs == ys and x == y, then x:xs == y:ys
foldr f z [] == z
foldr f z (x:xs) == f x (foldr f z xs)
EDIT: And to tie this to augustss' answer:
newtype ExpList a = ExpList (Maybe (a, ExpList a))
toExpList :: List a -> ExpList a
toExpList xs = runList xs (\x xs -> ExpList (Just (x, xs))) (ExpList Nothing)
foldExpList f z (ExpList Nothing) = z
foldExpList f z (ExpList (Just (head, taill))) = f head (foldExpList f z tail)
fromExpList :: ExpList a -> List a
fromExpList xs = List (\f z -> foldExpList f z xs)
You could define lists in terms of Maybe, but not that way do. Your List type cannot be empty. Or did you intend Maybe (List a) to be the replacement of [a]. This seems bad since it doesn't distinguish the list and maybe types.
This would work
newtype List a = List (Maybe (a, List a))
This has some problems. First using this would be more verbose than usual lists, and second, the domain is not isomorphic to lists since we got a pair in there (which can be undefined; adding an extra level in the domain).
If it's a list, it should be an instance of Functor, right?
instance Functor List
where fmap f (List a as) = List (f a) (mapMaybeList f as)
mapMaybeList :: (a -> b) -> Maybe (List a) -> Maybe (List b)
mapMaybeList f as = fmap (fmap f) as
Here's a problem: you can make List an instance of Functor, but your Maybe List is not: even if Maybe was not already an instance of Functor in its own right, you can't directly make a construction like Maybe . List into an instance of anything (you'd need a wrapper type).
Similarly for other typeclasses.
Having said that, with your formulation you can do this, which you can't do with standard Haskell lists:
instance Comonad List
where extract (List a _) = a
duplicate x # (List _ y) = List x (duplicate y)
A Maybe List still wouldn't be comonadic though.
When I first started using Haskell, I too tried to represent things in existing types as much as I could on the grounds that it's good to avoid redundancy. My current understanding (moving target!) tends to involve more the idea of a multidimensional web of trade-offs. I won't be giving any “answer” here so much as pasting examples and asking “do you see what I mean?” I hope it helps anyway.
Let's have a look at a bit of Darcs code:
data UseCache = YesUseCache | NoUseCache
deriving ( Eq )
data DryRun = YesDryRun | NoDryRun
deriving ( Eq )
data Compression = NoCompression
| GzipCompression
deriving ( Eq )
Did you notice that these three types could all have been Bool's? Why do you think the Darcs hackers decided that they should introduce this sort of redundancy in their code? As another example, here is a piece of code we changed a few years back:
type Slot = Maybe Bool -- OLD code
data Slot = InFirst | InMiddle | InLast -- newer code
Why do you think we decided that the second code was an improvement over the first?
Finally, here is a bit of code from some of my day job stuff. It uses the newtype syntax that augustss mentioned,
newtype Role = Role { fromRole :: Text }
deriving (Eq, Ord)
newtype KmClass = KmClass { fromKmClass :: Text }
deriving (Eq, Ord)
newtype Lemma = Lemma { fromLemma :: Text }
deriving (Eq, Ord)
Here you'll notice that I've done the curious thing of taking a perfectly good Text type and then wrapping it up into three different things. The three things don't have any new features compared to plain old Text. They're just there to be different. To be honest, I'm not entirely sure if it was a good idea for me to do this. I provisionally think it was because I manipulate lots of different bits and pieces of text for lots of reasons, but time will tell.
Can you see what I'm trying to get at?

Haskell custom isordered function to check a list of integers

I'm trying to write a Haskell function that checks if a list of integers is in order without using any of the already existing functions to order or check the order of the list. I have written the following code but I do not understand why it does not work. I get the error:
No instance for (Ord integer)
arising from a use of `<='
In the expression: x <= (head xs)
I don't understand what this means. Is there a different way that I should be writing this function? Here is my code so far.
isordered :: [integer] -> Bool
isordered [] = True
isordered (x:[]) = True
isordered (x:xs)|x <= (head xs) = isordered xs
|otherwise = False
Thanks in advance!!!
In Haskell type names start with capital letters and type variables start with lower case letters. So if you write integer, that's a type variable. So your type is the same as [a] -> Bool, i.e. you take a list of anything and return a Bool. So since there's no restriction on what type of item might be in the list, you're not allowed to use <= on it.
To fix this you can either just change it to Integer, which is what you wanted, or add an Ord constraint like this: Ord a => [a] -> Bool. The latter will make your function work with any type that implements the Ord typeclass (which provides the comparison operators such as <=).
What exactly counts as "already existing function"?
isordered xs = all (uncurry (<=)) $ zip xs (tail xs)
More low-level is
isordered (x:y:zs) = x <= y && isordered (y:zs)
isordered _ = True
Another way for doing it using guards:
isOrdered :: Ord a => [a] -> Bool
isOrdered (x:y:xs) | x<=y = isOrdered (y:xs)
| otherwise = False
isOrdered _ = True

Applying custom ordering to lists (to sort a list of lists)

There's an example of how to sort a list with a custom ordering at this page:
http://zvon.org/other/haskell/Outputlist/sortBy_f.html
xxx a b | odd a = LT
| otherwise = GT
Input: sortBy xxx [1,2,3,4,5,6,7]
Output: [1,3,5,7,6,4,2]
The standard less than order lets me compare lists, e.g.
[1,2,3] < [0,4,5]
Is False. But this doesn't work with the above example function:
Main> xxx [1,2,6] [1,7,3]
ERROR - Cannot infer instance
*** Instance : Integral [a]
*** Expression : xxx [1,2,6] [1,7,3]
Is there an easy way to extend such an order to lists?
The reason I want this functionality is to use sortBy to sort lists of lists using my custom ordering.
I'd be grateful for example solution code, advice on what to read up on, or anything in between. I'm hoping there's some built-in way to do this with the language rather than write a function that compares the lists directly.
You can convert a comparison function to a comparison function for lists with the code:
import Data.Monoid (mconcat)
compareList :: (a -> b -> Ordering) -> [a] -> [b] -> Ordering
compareList _ [] [] = EQ
compareList _ (_:_) [] = GT
compareList _ [] (_:_) = LT
compareList comparer (x:xs) (y:ys) =
comparer x y `mappend` compareList comparer xs ys
Now you can use xxx on two lists:
> compareList xxx [1,2,6] [1,7,3]
LT
> compareList xxx [2,2,6] [1,7,3]
GT
You could then use that to sort nested lists using your comparer:
> sortBy (compareList xxx) [[2,2,6], [1,7,3], [1,1,1]]
[[1,7,3],[1,1,1],[2,2,6]]
To replicate the behavior of < you would have to make your xxx function part of a type class. This is probably not worth it.
Instead, consider writing a new version of xxx specifically for lists:
xxxl :: Integral i => [i] -> [i] -> Ordering
xxx1 [] [] = EQ
xxxl [] _ = LT
xxxl _ [] = GT
xxxl (l1:_) (l2:_) | odd l1 = LT
| otherwise = GT
You might want to handle empty lists in some other fashion. This also illustrates why you cannot automatically generalize your xxx function to lists: how would you handle empty lists? You have to answer this question somehow, and writing a new function for lists is the easiest way.
You can now use your xxxl function with sortBy to sorts lists of lists: sortBy xxx ....