How isInBook from Chapter 3 works

I’m following the guide from https://book.purescript.org and have difficulties in the third exercise of chapter 3. As I understand the exercise, the output should be a boolean, depeding on if a name appears in the given AddressBook.

My implementation of isInBook is currently this:

isInBook :: String -> String -> AddressBook -> Boolean
isInBook firstName lastName = null <<< head <<< filter filterEntry
  where
  filterEntry :: Entry -> Boolean
  filterEntry entry = entry.firstName == firstName && entry.lastName == lastName

But I get this error message when enabling the isInBook test and running it:

$ spago test
Compiling Data.AddressBook
Error found:
in module Data.AddressBook
at src/Data/AddressBook.purs:48:31 - 48:67 (line 48, column 31 - line 48, column 67)

  Could not match type
         
    Maybe
         
  with type
        
    List
        

while trying to match type Maybe t2
  with type List t1
while checking that expression (compose head) (filter filterEntry)
  has type t0 -> List t1
in value declaration isInBook

where t0 is an unknown type
      t1 is an unknown type
      t2 is an unknown type

See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.


[error] Failed to build.

What did I miss when adding this functionality in?

The use of head in your composition is the problem:

filter filterEntry :: AddressBook -> AddressBook
head :: AddressBook -> Maybe Entry
null :: AddressBook -> Boolean

(I specialised the types above to how you are using them but it doesn’t change the outcome)

Note that once you have composed with head, composing with null will no longer type check as Maybe Entry does not unify with AddressBook.

In short:

isInBook firstName lastName = null <<< filter filterEntry
  where
  ...

However, notice that this does the opposite of what the function name implies: you reduce the list to a list that is either empty or contains the book you are searching for, and then you return true if the list is empty via null. eg If the book is in the list, null returns false, and if the book is not in the list, null returns true.

We can invert the behaviour by using not from prelude:

isInBook firstName lastName = not <<< null <<< filter filterEntry
  where
  ...
1 Like

Thanks for your help. It did solve it now