Rewbert
Rewbert

Reputation: 347

Faulty base-case Haskell

My functions:

type Block = [Maybe Int] 

checkBlock' :: Block -> Block
checkBlock' (r:rs)
    | r == [] = []
    | isJust r == True = r:checkBlock' rs
    | isNothing r == True = checkBlock' rs

checkBlock :: Block -> Block
checkBlock (r:rs)
    | r == [] = []
    | isNothing r == True = r:checkBlock rs
    | isJust r == True    = checkBlock rs

I want to first function to inspect a list of Just Ints and Nothings, and return only the Just values. And the second function to return only the Nothings.

They compile fine without the basecase where r == [] = [], but with it i get the error:

Sudoku.hs:104:12:
    Couldn't match expected type `Maybe Int' with actual type `[t0]'
    In the second argument of `(==)', namely `[]'
    In the expression: r == []
    In a stmt of a pattern guard for
                   an equation for checkBlock':
      r == []
Failed, modules loaded: none.

What can I place there instead of [] to make this compile? I've run ut of ideas.

Upvotes: 0

Views: 114

Answers (2)

viorior
viorior

Reputation: 1803

You can't compare r with empty list, you could compare the whole list only.

As an alternative, you could write

checkBlock :: Block -> Block
checkBlock rs
    | rs == [] = []
    | isNothing (head rs) == True = (head rs):checkBlock (tail rs)
    | isJust (head rs) == True    = checkBlock (tail rs)

Second, guards are already use Bool, so == True is unnecessary. by the way, try to use null rs istaed of rs == []

checkBlock :: Block -> Block
checkBlock rs
    | null rs              = []
    | isNothing (head rs)  = (head rs):checkBlock (tail rs)
    | isJust (head rs)     = checkBlock (tail rs)

But this looks a bit ugly, let's use pattern matching:

checkBlock :: Block -> Block
checkBlock [] = []
checkBlock (r:rs)
    | isNothing r  = r:checkBlock rs
    | isJust r     = checkBlock rs

Upvotes: 1

fjh
fjh

Reputation: 13091

You should use pattern matching here, not guards:

checkBlock :: Block -> Block
checkBlock [] = []
checkBlock (r:rs)
    | isNothing r == True = r:checkBlock rs
    | isJust r == True    = checkBlock rs

or, preferably:

checkBlock :: Block -> Block
checkBlock [] = []
checkBlock (Nothing : rs) = Nothing : checkBlock rs
checkBlock (Just _ : rs) = checkBlock rs

Upvotes: 2

Related Questions