Reputation: 61
I have three datatypes:
data Person = Person { firstName :: String
, lastName :: String
, age :: Int
, height :: Float
, phoneNumber :: String
, flavor :: String
} deriving (Eq,Show, Read)
data Car = Car {company :: String, model :: String, year :: Int} deriving (Eq,Show,Read)
data Things = C Car | P Person deriving (Eq,Show,Read)
And I want to find the Car's coordinates in a [[Things]].
I tried:
enumerate = zip [0..]
findCar :: [[Things]] -> [(Int, Int)]
findCar things = do
[(x, y)
| (y, row) <- enumerate things
, (x, thing) <- enumerate row
, thing == C (Car { })]
But I got an Exception: 'Missing field in record construction company'.
How can I find coordinates of Car in a [[Things]] in a proper way?
Upvotes: 1
Views: 687
Reputation: 152867
Rather than checking whether your thing
is equal to a specific Car
, which is what (==)
is for, you seem to want to check whether it's any kind of Car
. So:
isCar (C Car{}) = True
isCar _ = False
findCar things =
[ (x, y)
| (y, row) <- enumerate things
, (x, thing) <- enumerate row
, isCar thing
]
(I've removed the unnecessary and potentially confusing do
from findCar
.)
Alternately, you could use the behavior of failed pattern matches in list comprehensions:
findCar things =
[ (x, y)
| (y, row) <- enumerate things
, (x, C Car{}) <- enumerate row
]
This is a well-known trick, but a bit subtle and possibly confusing in a quick read of the code (since the match looks partial, but isn't), so it may be worth avoiding in a codebase shared between many programmers.
Upvotes: 5