6
votes

I have a list of tuples of tuples of type :: [((a, b), (a, b), (a, b))], in Haskell.

For some context, the 3 points (a, b) represent a (time, value) pair on a U shaped curve with the first point, at the initial time t1 having a maximum value on the curve x1, the third point with a greater time t3=t1+dt and a value x3

I would like find the range for the widest U in the list [((t1, x1), (t2, x2), (t3, x3))] by taking the tuple with the maximum t3 - t1, and then returning the value x2 - x1.

The only way I can think to do it is to first map each tuple in the list to t3 - t1, find its index, then calculate x2 - x1 for that index in the original list. Is there a more elegant way to do this?

findMaxTime :: [((a, b), (a, b), (a, b))] -> Int
findMaxTime list = elemIndex (==min) $ map (\(x, y, z) -> fst z - fst x)
                       where min = minimum $ map (\(x, y, z) -> fst z - fst x)

findMaxVal :: [((a, b), (a, b), (a, b))] -> b
findMaxVal list = list !! findMaxTime list

Any help would be appreciated.

Thanks, Ash

1

1 Answers

8
votes

You can use maximumBy with comparing:

module Main where

import Data.Ord (comparing)
import Data.List (maximumBy)

findMaxVal :: (Num a, Ord a, Num b, Ord b) => [((a, b), (a, b), (a, b))] -> b
findMaxVal = xWidth . maximumBy (comparing tWidth)
  where
    xWidth ((_, x1), (_, x2), _) = x2 - x1
    tWidth ((t1, _), _, (t3, _)) = t3 - t1