How do I create an applicative instance for ziplist? - list

I want to implement an instance of Applicative for my custom list.
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
instance Eq a => EqProp (List a) where (=-=) = eq
instance Functor List where
fmap _ Nil = Nil
fmap f (Cons a Nil) = (Cons (f a) Nil)
fmap f (Cons a as) = (Cons (f a) (fmap f as))
main = do
let trigger = undefined :: List (Int, String, Int)
quickBatch $ applicative trigger
instance Arbitrary a => Arbitrary (List a) where
arbitrary = sized go
where go 0 = pure Nil
go n = do
xs <- go (n - 1)
x <- arbitrary
return (Cons x xs)
instance Applicative List where
pure x = (Cons x Nil)
Nil <*> _ = Nil
_ <*> Nil = Nil
(Cons f fs) <*> (Cons a as) = (Cons (f a) (fs <*> as))
This gives the following bugs:
λ> main
applicative:
identity: *** Failed! Falsifiable (after 3 tests):
Cons 0 (Cons (-1) Nil)
composition: *** Failed! Falsifiable (after 3 tests):
Cons <function> (Cons <function> Nil)
Cons <function> (Cons <function> Nil)
Cons 1 (Cons (-2) Nil)
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: *** Failed! Falsifiable (after 3 tests):
<function>
Cons (-2) (Cons (-1) Nil)
First is the id law is failing:
λ> Cons id Nil <*> Cons 0 (Cons (-1) Nil)
Cons 0 Nil
How do I fix this? pure takes an a not a List a so I do not see how to match on List and preserve the nested list structure.
The composition law also fails which is not strange:
λ> (Cons "b" Nil) <*> (Cons "c" Nil)
<interactive>:295:7:
Couldn't match expected type ‘[Char] -> b’
with actual type ‘[Char]’
Relevant bindings include
it :: List b (bound at <interactive>:295:1)
In the first argument of ‘Cons’, namely ‘"b"’
In the first argument of ‘(<*>)’, namely ‘(Cons "b" Nil)’
In the expression: (Cons "b" Nil) <*> (Cons "c" Nil)
Edit: since I got great answers implementing applicative for ziplists, I have changed the question to be about ziplists.

For your ZipList-like approach we expect the following left-identity to hold:
pure id <*> someList = someList
For this, pure cannot return a single-element list, since this will stop immediately:
(Cons id Nil) <*> Cons 1 (Cons 2 Nil)
= Cons (id 1) (Nil <*> Cons 2 Nil)
= Cons 1 Nil
Which isn't the expected result for the left-identity. If pure cannot return only a single element list, how many should it return? The answer is: infinite:
repeatList :: a -> List a
repeatList x = let c = Cons x c in c
Why did I call this the ZipList approach? Because it's the same behaviour as in Control.Applicative.ZipList, which can be motivated with zipWith:
zipWithList :: (a -> b -> c) -> List a -> List b -> List c
zipWithList f (Cons x xs) (Cons y ys) = Cons (f x y) (zipWithList f xs ys)
zipWithList _ _ _ = Nil
Now your instance is
instance Applicative List where
pure = repeatList
(<*>) = zipWithList ($)
However, checkers cannot check this instance either due to your EqProb instance, since pure f <*> pure x == pure (f x) (homomorphism) results in a check on infinite lists. You can provide an alternative one, though. For example, you can take an arbitrary number of elements and compare them:
prop_sameList :: Eq a => (Int, Int) -> List a -> List a -> Property
prop_sameList bounds xs ys = forAll (choose bounds) $ \n ->
takeList n xs `eq` takeList n ys
takeList :: Int -> List a -> List a
takeList _ Nil = Nil
takeList n (Cons x xs)
| n <= 0 = Nil
| otherwise = Cons x (takeList (n - 1) xs)
Then, if you want to compare at least 1000 and at most 10000 elements, you can use:
instance Eq a => EqProb (List a) where
(=-=) = prop_sameList (1000, 10000)
After all, we're just trying to find a list where our property does not hold.

Expanding on my comment to Zeta's much more deserving answer, you need a second change to get this test to run:
-- | Test lists for equality (fallibly) by comparing finite prefixes
-- of them. I've arbitrarily chosen a depth of 1,000. There may be
-- better ideas than that.
instance Eq a => EqProp (List a) where
xs =-= ys = takeList 1000 xs `eq` takeList 1000 ys
-- | Take a prefix of up to #n# elements from a 'List'.
takeList :: Int -> List a -> List a
takeList _ Nil = Nil
takeList n (Cons a as)
| n > 0 = Cons a (takeList (n-1) as)
| otherwise = Nil
With Zeta's changes and this one, your test suite passes:
applicative:
identity: +++ OK, passed 500 tests.
composition: +++ OK, passed 500 tests.
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: +++ OK, passed 500 tests.
The key insight to get here is that QuickCheck is, fundamentally, a tool for finding counterexamples to properties. QuickCheck generally cannot prove that a property holds for all possible inputs, because the domain may be infinite. That's the reason why there's an EqProp class in checkers ("Types of values that can be tested for equality, perhaps through random sampling")—so that we may implement techniques for searching for counterexamples for types and tests that don't admit of simple equality comparisons.

Related

How to use custom version of List: `data List a = Nil | Cons a (List a)`?

This question is based on an example from the chapter "Declaring Types and Classes" of the book "Programming in Haskell" by Graham Hutton, second edition.
The data declaration is:
data List a = Nil | Cons a (List a)
The example function that uses this declaration is:
len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs
But no matter what I've tried, I can't seem to use the function len:
len Cons 1 Cons 2 Cons 3
len 1
len Cons
len (1)
len [1,2]
len Cons [1]
len (1,2)
len Cons (1,2)
len Cons 1 2
len (Cons (1,2))
len (Cons 1 2)
Did I miss out any permutation of len and Cons? Or is the example simply unworkable?
The parameters you pass to the len are not Lists. The end of a list has Nil, so lists are of the form Nil, Cons … Nil, Cons … (Cons … Nil), Cons … (Cons … (Cons … Nil)), etc. So eventually for each list, the end of the list is marked with Nil. Nil is the equivalent to [] for Haskell's [a] type.
Furthermore you can not pass len Cons 1 Nil for example, since then it will be interpreted as ((len Cons) 1) Nil. The parameter should be a list. By using parenthesis, you can write this as len (Cons 1 Nil).
For the given sample data, you thus can rewrite this to:
len Cons 1 Cons 2 Cons 3 → len (Cons 1 (Cons 2 (Cons 3 Nil)))
len 1 → len (Cons 1 Nil)
len Cons → len Nil
len (1) → len (Cons 1 Nil)
len [1,2] → len (Cons 1 (Cons 2 Nil))
len Cons [1] → len (Cons 1 Nil)
len (1,2) → len (Cons 1 (Cons 2 Nil))
len Cons (1,2) → len (Cons 1 (Cons 2 Nil))
len Cons 1 2 → len (Cons 1 (Cons 2 Nil))
len (Cons (1,2)) → len (Cons 1 (Cons 2 Nil))
len (Cons 1 2) → len (Cons 1 (Cons 2 Nil))
You can also make use of the OverloadedLists [haskell-doc] extension to use list syntax instead. In that case, you need to implement the IsList type class:
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts(IsList(..))
data List a = Nil | Cons a (List a)
instance IsList (List a) where
type Item (List a) = a
toList Nil = []
toList (Cons x xs) = x : toList xs
fromList [] = Nil
fromList (x:xs) = Cons x (fromList xs)
If you then enable the OverloadedLists extension, you can write these as list literals:
{-# LANGUAGE OverloadedLists #-}
-- …
main = print (len [1,2])
You use a function exactly as it is defined:
len Nil = 0
len (Cons _x xs) = 1 + len xs
then,
list1 = Nil -- matches the first pattern
list2 = Cons 2 list1 -- matches the second pattern
list3 = Cons 3 list2 -- matches the second pattern
list4 = Cons 4 list3 -- matches the second pattern
and so on and so forth.
Writing out such example data by hand we need to use parentheses to correctly group the sub-terms to recreate the valid term, as e.g.
list5 = Cons 5 list4
= Cons 5 (Cons 4 list3)
= Cons 5 (Cons 4 (Cons 3 list2))
= ...
= Cons 5 (Cons 4 (Cons 3 (Cons 2 Nil)))
All this without even having looked at the data type definition.
Of course anything can be used in place of 1, 2, etc., as long as they are all of the same type, e.g. the following is also a valid term:
list54 = Cons list5 (Cons list4 Nil)
Why? Because of the data type definition,
data List a = Nil -- `Nil` constructs (is) a valid `List a` type term,
| -- OR,
Cons -- `Cons x xs` constructs (is) a valid `List a` type term, IF
a -- `x` is a valid term of type `a` , AND
(List a) -- `xs` is a valid term of type `List a`
Nil constructs (is) a valid List a type term, while Cons x xs constructs (is) a valid List a type term, if x is a valid term of type a and xs is a valid term of type List a, where a is one and the same.
So e.g. Cons 1 (Cons list2 Nil) is not a valid term according to the List a data type definition, even though the function len could seemingly handle it as well.

My redefinition of Haskell 'length' function won't work

Can someone please explain how I can fix my program.
Very new to Haskell, been trying to create a length function that calculates the length of a list of any type.
I am aiming to do this using data as I want to create a brand new type to do so (this is the area of Haskell that I'm currently learning, which is why it might not be the most efficient implementation of this function)
data List a = Nil | Cons a (List a)
len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs
If I run it on len [1,2,3]
I get the error:
• Couldn't match expected type ‘List a0’
with actual type ‘[Integer]’
• In the first argument of ‘len’, namely ‘[1, 2, 3]’
In the expression: len [1, 2, 3]
In an equation for ‘it’: it = len [1, 2, 3]
The function definition is correct, but [1,2,3] is not a List a object, it is a [a] (or more canonical [] a). A list like [1,2,3] as List Int is:
len (Cons 1 (Cons 2 (Cons 3 Nil)))
Alternatively, you can make List a an instance of the IsList type class, and then use the -XOverloadedLists extension:
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts(IsList(Item, fromList, toList))
instance IsList (List a) where
type Item (List a) = a
fromList = foldr Cons Nil
toList Nil = []
toList (Cons x xs) = x : toList xs
Then we can use the OverloadedLists extension:
$ ghci -XOverloadedLists -XTypeFamilies
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/kommusoft/.ghci
Prelude> data List a = Nil | Cons a (List a)
Prelude> import GHC.Exts(IsList(Item, fromList, toList))
Prelude GHC.Exts> :{
Prelude GHC.Exts| instance IsList (List a) where
Prelude GHC.Exts| type Item (List a) = a
Prelude GHC.Exts| fromList = foldr Cons Nil
Prelude GHC.Exts| toList Nil = []
Prelude GHC.Exts| toList (Cons x xs) = x : toList xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> :{
Prelude GHC.Exts| len :: List a -> Int
Prelude GHC.Exts| len Nil = 0
Prelude GHC.Exts| len (Cons _ xs) = 1 + len xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> len [1,2,3]
3

data List - checking if a list is empty

I have the following. It just simply checks if a List is empty. However if I try to run it with main, I get an error. How do I need to change the main function to run it properly?
data List a = Nil | Cons a (List a)
vnull :: List a -> Bool
vnull Nil = True
vnull _ = False
main = do print (vnull [1,2])
The error is the following:
Couldn't match expected type `List a0' with actual type `[Integer]'
In the first argument of `vnull', namely `[1, 2]'
In the first argument of `print', namely `(vnull [1, 2])'
In a stmt of a 'do' block: print (vnull [1, 2])
Changing to:
main = print $ vnull $ Cons 1 $ Cons 2 Nil
produces:
False
If you want to be able to use your List type with the usual list syntax, you'll have to use GHC extensions.
{-# LANGUAGE OverloadedLists, TypeFamilies #-} -- at the very top of the file
import qualified GHC.Exts as E
import Data.Foldable
data List a = Nil | Cons a (List a) deriving (Show, Eq, Ord)
instance Foldable List where
foldr _ n Nil = n
foldr c n (Cons x xs) = x `c` foldr c n xs
instance E.IsList List where
type Item (List a) = a
fromList = foldr Cons Nil
toList = toList
it is working like it is implemented:
vnull Nil
True
vnull (Cons 1 Nil)
False
vnull (Cons 2 (Cons 1 Nil)
False
...
you can try following commands in ghci, to get all information about [] datatype:
Prelude> :t []
[] :: [t]
Prelude> :i []
data [] a = [] | a : [a] -- Defined in ‘GHC.Types’
instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
instance Monad [] -- Defined in ‘GHC.Base’
instance Functor [] -- Defined in ‘GHC.Base’
instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
instance Read a => Read [a] -- Defined in ‘GHC.Read’
instance Show a => Show [a] -- Defined in ‘GHC.Show’
instance Applicative [] -- Defined in ‘GHC.Base’
instance Foldable [] -- Defined in ‘Data.Foldable’
instance Traversable [] -- Defined in ‘Data.Traversable’
instance Monoid [a] -- Defined in ‘GHC.Base’
for your function to be applicable to [] parameter you need something like:
vnull :: [a] -> Bool
vnull [] = True
vnull _ = False
This is what you are missing:
data List a = Nil | Cons a (List a) deriving Show
fromList = foldr Cons Nil
vnull :: List a -> Bool
vnull Nil = True
vnull _ = False
main = do print (vnull $ fromList [1,2])
The deriving Show is not necessary now, but will be, when you actually want to print a List and not a Bool. The fromList function does nothing, but to convert the Haskell Listimplementation (here [1,2]) into your own, so you can call vnull on it. You could have also called
main = do print $ vnull (Cons 1 (Cons 2 (Nil)))
List a
and
[]
Are two different constructors and not the same data type, The function would work for a List a type, so instead of "[]" try this:
vnull :: List a -> Bool
vnull Nil = True
vnull (Cons a expand) = False
Then in main
main = do print (vnull $ Cons 1 (Cons 2 Nil)) --This is just an example you can throw in a -List a- type of any length.
And this should fix it.
You can:
instance Foldeable List where
foldMap f Nil = mempty
foldMap f (Cons x ls) = mappend (f x) (foldMap ls)
Then use (fold [1,2])::List Int

How to define Eq instance of List without GADTs or Datatype Contexts

I am using Glasgow Haskell Compiler, Version 7.8.3, stage 2 booted by GHC version 7.6.3.
I attempted to use the following data definition for a List type in Haskell:
data Eq a => List a = Nil | Cons a (List a)
However, the -XDatatypeContexts flag is required, depricated, and even removed from the language by default. It is widely viewed as a misfeature of the language. I also do not want to have to use special flags for my definition of List since I am trying to replicate the functionality of the existing list type.
Then I was able to use the following segment of code instead:
data List a where
Nil :: List a
Cons :: Eq a => a -> List a -> List a
It runs fine. The visible issue with this solution is that now I need to use the -XGADTs flag, which I still don't want to depend on in this case since it is not necessary for the built in version of list to function. Is there a way to restrict the type within Cons to be Eq a so that I can compare two lists without the need for compiler flags and without using the derived keyword?
The remaining code is as follows:
instance Eq (List a) where
(Cons a b) == (Cons c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
testfunction = Nil :: List Int
main = print (if testfunction == Nil then "printed" else "not printed")
I see that the following solution works:
data List a = Nil | Cons a (List a)
instance Eq a => Eq (List a) where
(Cons a b) == (Cons c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
testfunction = Nil :: List Int
main = print (if testfunction == Nil then "printed" else "not printed")
However, for some reason, it does not work with a manual definition for Eq (Equals here).
class Equal a where
(=+=) :: a -> a -> Bool
(/+=) :: a -> a -> Bool
x =+= y = not (x /+= y)
x /+= y = not (x =+= y)
data List a = Nil | Cons a (List a)
instance Equal a => Equal (List a) where
(Cons a b) =+= (Cons c d) = (a =+= c) && (b =+= d)
Nil =+= Nil = True
_ =+= _ = False
testfunction = Nil :: List Int
main = print (if testfunction =+= Nil then "printed" else "not printed")
I get the following error:
No instance for (Equal Int) arising from a use of ‘=+=’
In the expression: testfunction =+= Nil
In the first argument of ‘print’, namely
‘(if testfunction =+= Nil then "printed" else "not printed")’
In the expression:
print (if testfunction =+= Nil then "printed" else "not printed")
However, by using GADT's, I can show that my Equal class does actually function. This code works:
class Equal a where
(=+=) :: a -> a -> Bool
(/+=) :: a -> a -> Bool
x =+= y = not (x /+= y)
x /+= y = not (x =+= y)
data List a where
Nil :: List a
Cons :: Equal a => a -> List a -> List a
instance Equal (List a) where
(Cons a b) =+= (Cons c d) = (a =+= c) && (b =+= d)
Nil =+= Nil = True
_ =+= _ = False
testfunction = Nil :: List Int
main = print (if testfunction =+= Nil then "printed" else "not printed")
However, I have to use instance Equal (List a) where instead of instance Equal a => Equal (List a) where otherwise I get the error:
No instance for (Equal Int) arising from a use of ‘=+=’
In the expression: testfunction =+= Nil
In the first argument of ‘print’, namely
‘(if testfunction =+= Nil then "printed" else "not printed")’
In the expression:
print (if testfunction =+= Nil then "printed" else "not printed")
It looks like you're trying to restrict lists to only be able to hold values that implement Eq, and you can't do that without extensions. You can, however, tell the compiler how to compare two List as when a has a type that implements Eq. There are two easy ways to do this. The simplest is with a deriving statement:
data List a = Nil | Cons a (List a) deriving (Eq)
Or you can define it manually:
instance Eq a => Eq (List a) where
(Cons a b) == (Const c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
Now whenever you fill your List type with something that implements Eq, the list will also be comparable using ==. There's no need to restrict the values that can be inside Cons. You can certainly have a normal list of functions, like
fs1 :: [Int -> Int]
fs1 = [(+1), (*3), (+2), (*4)]
Or in your case
fs2 :: List (Int -> Int)
fs2 = Cons (+1) $ Cons (*3) $ Cons (+2) $ Cons (*4) Nil
Which can be used as
> map ($ 10) fs1
[11, 30, 12, 40]
And given
map' :: (a -> b) -> List a -> List b
map' f Nil = Nil
map' f (Cons x xs) = Cons (f x) (map' f xs)
Then
> map' ($ 10) fs2
Cons 11 (Cons 30 (Cons 12 (Cons 40 Nil)))
Although to actually view it in GHCi you should also derive Show:
data List a = Nil | Cons a (List a) deriving (Eq, Show)
There are several other useful typeclasses that can be derived in GHC, too.
To make it work with your custom Equal typeclass, you'll have to write multiple instances by hand:
class Equal a where
(=+=) :: a -> a -> Bool
(/+=) :: a -> a -> Bool
x =+= y = not (x /+= y)
x /+= y = not (x =+= y)
instance Equal Int where
x =+= y = x == y
instance Equal a => Equal (List a) where
(Cons a b) =+= (Cons c d) = (a =+= c) && (b =+= d)
Nil =+= Nil = True
_ =+= _ = False
Now because you have an instance Equal Int and Equal a => Equal (List a), you can compare two List Ints:
> let x = Cons 1 (Cons 2 (Cons 3 Nil)) :: List Int
> let y = Cons 1 (Cons 2 (Cons 3 Nil)) :: List Int
> x =+= y
True
> x =+= Nil
False
For whatever type you want to store in a List and use =+= on, you'll have to implement Equal for that type.
The usual solution to this is to to use this structure:
data List a = Nil | Cons a (List a)
instance Eq a => Eq (List a) where
(Cons a b) == (Cons c d) = (a == c) && (b == d)
Nil == Nil = True
_ == _ = False
Noticed I've added Eq a as a constraint to the instance, not to the data type. This way all the lists that you could compare for equality the way you're trying to write it can be compared for equality, but you also allow the existence of lists of things which cannot be compared for equality. And this is supported by every version of Haskell you will encounter, even very old ones, with no extensions.
This approach then also extends nicely when you want to add a Show instance, an Ord instance, etc; to do it your way you have to keep going back and making the data structure more restrictive by adding more constraints (potentially breaking existing code that worked fine because it didn't need those instances). Whereas if you leave the data type unconstrained and just make your instances Show a => Show (List a), Ord a => Ord (List a), etc, then you can show and order lists of types which happen to support both, but you can still have (and show) lists of types that support Show but not Ord and vice versa.
Plus, there are lots of useful type classes for parameterised types (such as List a) that require them to be fully generic in their type parameter. Examples are Functor, Applicative, Monad; it is not possible to correctly implement these for the constrained list type you're trying to create.
While it is possible to create constrained lists like you're trying to (but only by using extensions, as you've found), it has been found to be usually much more useful to leave your data types fully generic in their type parameter, and if a particular usage of your type needs to impose restrictions on the type parameter you impose them at that usage site, not at every use of the data type. This should be your "default setting"; depart from it when you have a good reason (you may well have such a reason here, but you haven't given it to us in the question, so nobody can recommend the best way of handling it).

Haskell writing a Filter for selfdefined List

Heyho.
I am learning Haskell at University right now. There is a task I just can't wrap my head around. I don't understand why this won't compile. Hope someone can help me.
They gave us a self defined List and now we are supposed to create Filter that works with this list just like the Filter from the bib.
Here's the code:
data List a = Nil | Cons a (List a) deriving Show
list :: List Int
list = Cons (-3) (Cons 14 (Cons (-6) (Cons 7 (Cons 1 Nil))))
filterList :: (a -> Bool) -> List a -> List a
filterList f Nil = Nil
filterList f (Cons e l) | f e = e : (filterList f l)
| otherwise = (filterList f l)
Your recursive call for the first case is wrong: You want to do Cons e (filterList f l) but you actually use (:) and not Cons. Reason for this being that e : (filterList f l) has type [a] but you actually want List a.
To solve this, just change
e : (filterList f l)
to
Cons e (filterList f l)
since you want it to return your the "non-standard" List type.
e : (filterList f l) is not a List a but a [a], use Cons e (filterList f l) instead.
(By the way, always post the error for this kind of questions. It may say nothing to you, but it often greatly helps us in answering.)