[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 Control.Monad.Identity
import Control.Monad.Error
import Control.Monad
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






More information about the Beginners mailing list