- From last week:
**data****Suit****=****Spades****|****Hearts****|****Diamonds****|****Clubs****data****Rank****=****Numeric****Int****|****Jack****|****Queen****|****King****|****Ace****data****Card****=****Card****Rank****Suit****data****Hand****=****Empty****|****Add****Card****Hand**

**data****Hand****=****Empty****|****Add****Card****Hand**- The two constructors and
**Empty**allows us to construct "lists" of cards of arbitrary length.**Add****Empty****Add**`c1`**Empty****Add**`c2`(**Add**`c1`**Empty**)**Add**`c3`(**Add**`c2`(**Add**`c1`**Empty**))- ...

`colour`**::****Suit****->****Colour**`colour`**Spades****=****Black**`colour`**Clubs****=****Black**`colour`**_****=****Red**`rank`**::****Card****->****Rank**`rank`(**Card**`r``s`)**=**`r``handBeats`**::****Hand****->****Card****->****Bool**`handBeats`**Empty**`beat`**=****False**`handBeats`(**Add**`c``h`)`beat`**=**`cardBeats``c``beat``||``handBeats``h``beat`- Functions on the values of a datatype are usually defined by pattern matching.
- Recursive datatype => recursive functions (typically).

- Haskell has a predefined type and special syntax for lists.
- Lists contain 0, 1, 2, or more values.
- ,
[]

,`[3]`

["Haskell","JavaScript","C","Python"]

- All values in a list have the same type
- causes a type error.
[1,3,

**True**,"Python"]

- The order matters
[1,2,3]

`/=`[3,2,1]

- But how is the list type defined, what's special about it?

- The natural way to define the list type would be like this:
**data****List**`a`**=****Nil****|****Cons**`a`(**List**`a`)- Types can have type parameters!

- The predefined list type is essentially the same, only with some special syntax:
**data**[`a`]**=**[]**|**`a`**:**[`a`]- So, all lists are built using two constructors:
- , the empty list.
[]

- , extending a list by adding one more value
`x`**:**`xs`to the front of an existing list`x`.`xs`

5

**:**( 6**:**(3**:**[]))`==`5**:**6**:**3**:**[]`==`[5,6,3]"Haskell"

`==`['H','a','s','k','e','l','l']**type****String**= [**Char**]

- Since the list type allow arbitrary element types, it is natural that many functions on lists are "generic" and allow arbitrary element types too. For example:
`length`**::**[`a`]**->****Int**(`++`)**::**[`a`]**->**[`a`]**->**[`a`]`concat`**::**[[`a`]]**->**[`a`]`take`**::****Int****->**[`a`]**->**[`a`]`zip`**::**[`a`]**->**[`b`]**->**[(`a`,`b`)]`map`**::**(`a`**->**`b`)**->**[`a`]**->**[`b`]`filter`**::**(`a`**->****Bool**)**->**[`a`]**->**[`a`]

- There are also functions for specific types of lists. for example:
`and`,`or`**::**[**Bool**]**->****Bool**`words`,`lines`**::****String****->**[**String**]`unwords`,`unlines`**::**[**String**]**->****String**- Overloaded list functions
`sum`,`product`**::****Num**`a`**=>**[`a`]**->**`a``elem`**::****Eq**`a`**=>**`a`**->**[`a`]**->****Bool**`sort`**::****Ord**`a`**=>**[`a`]**->**[`a`]

- length, sum
- append, reverse,
- take, drop, splitAt,
- zip, unzip,
- insert, isort, qsort
- QuickCheck: collect, classify
- Source code: WorkingWithLists.hs

qsort::Orda=>[a]->[a]qsort[]=[]qsort(x1:xs)=qsortsmaller++[x1]++qsortbiggerwheresmaller=[x|x<-xs,x<=x1]bigger=[x|x<-xs,x>x1]

`prop_take_drop``n``xs`**=**`take``n``xs``++``drop``n``xs``==``xs``nonprop_take_drop``n``xs`**=**`drop``n``xs``++``take``n``xs``==``xs``quickCheck prop_take_drop`

+++ OK, passed 100 tests.`quickCheck nonprop_take_drop`

+++ OK, passed 100 tests.- Not good! Checking the types
`prop_take_drop`**::****Eq**`a`**=>****Int****->**[`a`]**->****Bool**`nonprop_take_drop`**::****Eq**`a`**=>****Int****->**[`a`]**->****Bool**- QuickCheck doesn't work on polymorphic types, somehow a more specific type got selected.

- GHCi tries to be helpful by choosing a specific type instead of complaining about unresolved overloading.
- This means that will test
`quickCheck``nonprop_take_drop``nonprop_take_drop`**::****Int****->**[()]**->****Bool**

- GHCi picks the unit type , a type containing only one value
()

.()

**data**()**=**()

- But when all elements in the list are the same, it doesn't matter in which order we put them!
- The test is good if we only care about the length of the lists.

- Use type signatures to avoid defaulting to the unit type.
- In the source code, or
when calling .
`quickCheck`

- In the source code, or
when calling
- Disable extended defaulting in GHCi to be safe:
`:set -XNoExtendedDefaultRules`

- You will get en error message instead of a potentially meaningless test result.

- Or restrict the types used in defaulting to the standard ones:
`default (Integer,Double)`