user2328270
user2328270

Reputation: 31

Extracting single integer in Haskell from list

Totally new to Haskell. Problem- I have a type constructor with a value constructor consisting of 4 components:

 TrackPoint :: TP { rpm :: Integer
               , time :: Integer
               , distance :: Float
               , speed :: Float 
               } deriving (Show)

I would like to take [TrackPoint] and have it return time, distance and speed anytime the rpm value is below 10,000. I have tried using guards with no luck. Any help would be appreciated by this novice.

Upvotes: 3

Views: 116

Answers (2)

Nikita Volkov
Nikita Volkov

Reputation: 43309

Simple function:

processTrackPoints :: [TrackPoint] -> [(Integer, Float, Float)]
processTrackPoints tps = 
  map (\tp -> (time tp, distance tp, speed tp)) $
  filter (\tp -> rpm tp > 10000) tps

Same, but point-free where possible:

processTrackPoints :: [TrackPoint] -> [(Integer, Float, Float)]
processTrackPoints = 
  map (\tp -> (time tp, distance tp, speed tp)) .
  filter ((> 10000) . rpm)

Using guards:

processTrackPoints :: [TrackPoint] -> [(Integer, Float, Float)]
processTrackPoints ((TP rpm time distance speed) : t)
  | rpm > 10000 = (time, distance, speed) : processTrackPoints t
  | otherwise = processTrackPoints t
processTrackPoints _ = []

That is all, of course, assuming, that you have the datatype defined correctly like this:

data TrackPoint = 
  TP { 
    rpm :: Integer, 
    time :: Integer, 
    distance :: Float, 
    speed :: Float 
  } 
  deriving (Show)

Upvotes: 3

Jon Purdy
Jon Purdy

Reputation: 54971

It’s easy to do with comprehensions:

[ (time, distance, speed)
| TP rpm time distance speed <- trackPoints
, rpm < 10000
]

Even easier with {-# LANGUAGE RecordWildCards #-}:

[ (time, distance, speed)
| TP{..} <- trackPoints
, rpm < 10000
]

The convention for records in Haskell is usually to prefix them to avoid name collisions, e.g., tpRpm. It’s also worthwhile to remember that list comprehensions are just sugar for the list monad:

timesDistancesAndSpeedsOrSomeBetterName <- do
  TP{..} <- trackPoints
  guard (rpm < 10000)
  return (time, distance, speed)

Upvotes: 1

Related Questions