I'm very new to using Haskell and I'm unsure about how 'head' works. From my understanding it returns the first element in a list. I've been trying to use it, but I keep getting errors. I added a workaround by creating a separate function that finds the head, however that seems like it should be unnecessary.
I don't understand why calling findHead here:
single x = length (snd(x)) == 1
toList board
| board == [] = []
| otherwise = filter single board
findHead board = head (toList board)
is not equivalent to calling toList here:
single x = length (snd(x)) == 1
toList board
| board == [] = []
| otherwise = head (filter single board)
It seems to me that the two should be the same, but only the first one runs. Why aren't they interpreted to be the same? Could you explain this to me? In the code above, 'board' is meant to be a list of tuples which are each the form (x, [a,b,...]).
I've used 'head' in a few simpler things like:
union xs ys
| xs == [] = ys
| ys == [] = xs
| otherwise = union (tail xs) (add (head xs) ys)
which seems to work as I would expect it would.
head
is partial. In particular, head []
doesn't return normally (throws an exception). This can be difficult to handle in Haskell which is why people often suggest that you avoid partial functions.
So how do we do that? We have to reflect failure in the type.
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (a:as) = Just a
A similar function can be made for tail
safeTail :: [a] -> Maybe [a]
safeTail [] = Nothing
safeTail (a:as) = Just as
I think you need to take a step back and understand how pattern matching, recursion and single-linked lists work. As various people have mentioned, the code you're writing is not going to work very well.
As an illustration here's how I would write the various functions in your question:
single :: (a, [b]) -> Bool
single (_, [_]) = True
single _ = False
toList :: [(a, [b])] -> [(a, [b])]
toList board = filter single board
findHead :: [(a, [b])] -> Maybe (a, [b])
findHead [] = Nothing
findHead board = head (toList board)
-- This one actually does the same thing as the built-in `++` operator,
-- but for the sake of illustration, I'll implement it.
union :: [a] -> [a] -> [a]
union [] ys = ys
union (x:xs) ys = x : union xs ys
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With