[Haskell-beginners] maybe this could be improved?

Michael P Mossey mpm at alumni.caltech.edu
Wed Nov 11 21:15:36 EST 2009

```Patrick LeBoutillier wrote:
> Michael,
>
> Your code is interesting and I'd like to run it, but I'm not to
> familiar with Maps and Monad transformers.
> Could you provide a function to create a SampleMap and a way to test
> it from ghci?
>

Sure,

import qualified Data.Map as M

type Pitch = Int
type Sample = String
type SampleMap = M.Map Pitch Sample

-- Given a SampleMap and a Pitch, find the Pitch in the SampleMap
-- which is closest to the supplied Pitch and return that. Also
-- handle case of null map by throwing an error.
findClosestPitch :: SampleMap -> Pitch -> ErrorT String Identity Pitch
findClosestPitch samples inPitch = do
when (M.null samples) \$ throwError "Was given empty sample table."
case M.splitLookup inPitch samples of
(_,Just _,_ ) -> return inPitch
(m1,_        ,m2) | (M.null m1) && not (M.null m2) -> case1
| not (M.null m1) && (M.null m2) -> case2
| otherwise                      -> case3
where case1 = return . fst . M.findMin \$ m2
case2 = return . fst . M.findMax \$ m1
case3 = return \$ closest (fst . M.findMax \$ m1)
(fst . M.findMin \$ m2)
closest a b = if abs (a - inPitch) < abs (b - inPitch)
then a
else b

testMap1 = M.fromList [ (1,"sample1")
, (5,"sample2")
, (9,"sample3") ]

-- testMap2 ==> Right 1
testMap2 = runIdentity \$ runErrorT \$ findClosestPitch testMap1 2

-- testMap3 ==> Right 5
testMap3 = runIdentity \$ runErrorT \$ findClosestPitch testMap1 5

-- testMap4 ==> Left "Was given empty sample table."
testMap4 = runIdentity \$ runErrorT \$ findClosestPitch M.empty 5

```