Changeset 3495 for src/Pugs/Prim/List.hs

Show
Ignore:
Timestamp:
05/20/05 12:01:14 (4 years ago)
Author:
iblech
svk:copy_cache_prev:
5078
Message:

Implemented min() and max() (work with and without a userspecified comparision
sub) and added more (successful! :)) tests for them.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Prim/List.hs

    r3477 r3495  
    11module Pugs.Prim.List ( 
    22    op0Zip, op1Pick, op1Sum, 
     3    op1Min, op1Max, 
    34    op2FoldL, op2Fold, op2Grep, op2Map, op2Join, 
    45    sortByM, 
     
    1011 
    1112import Pugs.Prim.Numeric 
     13import Pugs.Prim.Lifts 
    1214 
    1315op0Zip :: [Val] -> Eval Val 
     
    4749    vals <- fromVal list 
    4850    foldM (op2Numeric (+)) undef vals 
     51 
     52op1Min :: Val -> Eval Val 
     53op1Min v = op1MinMax (== False) v 
     54 
     55op1Max :: Val -> Eval Val 
     56op1Max v = op1MinMax (== True) v 
     57 
     58-- min_or_max is a function which negates truth/falsehood. 
     59-- This is necessary as op1MinMax should cope with min() as well as max(). 
     60op1MinMax :: (Bool -> Bool) -> Val -> Eval Val 
     61op1MinMax min_or_max v = do 
     62    -- We want to have a real Haskell list 
     63    args    <- fromVal v 
     64    -- Extract our comparator sub, or Nothing if none was specified 
     65    (valList, cmp) <- case args of 
     66        (v:vs) -> do 
     67            ifValTypeIsa v "Code" 
     68                (return (vs, Just v)) 
     69                (ifValTypeIsa (last args) "Code" 
     70                    (return (init args, Just $ last args)) 
     71                    (return (args, Nothing))) 
     72        _  -> return (args, Nothing) 
     73    -- Now let our helper function do the rest 
     74    op1MinMax' min_or_max cmp valList 
     75    where 
     76    op1MinMax' :: (Bool -> Bool) -> (Maybe Val) -> [Val] -> Eval Val 
     77    -- The min or max of an empty list is undef. 
     78    op1MinMax' _ _ [] = return undef 
     79    -- We have to supply our own comparator... 
     80    op1MinMax' _ Nothing valList = foldM default_compare (head valList) valList 
     81    -- or use the one of the user 
     82    op1MinMax' min_or_max (Just subVal) valList = do 
     83          sub <- fromVal subVal 
     84          evl <- asks envEval 
     85          -- Here we execute the user's sub 
     86          foldM (\a b -> do 
     87              rv  <- local (\e -> e{ envContext = cxtItem "Int" }) $ do 
     88                  evl (App (Val sub) [Val a, Val b] []) 
     89              int <- fromVal rv 
     90              -- If the return value from the sub was 
     91              --   -1 ==> a < b 
     92              --    0 ==> a == b 
     93              --   +1 ==> a > b 
     94              -- We call min_or_max so we can work for both min() and max(). 
     95              return $ if min_or_max (int > (0::VInt)) then a else b) (head valList) valList 
     96    -- This is the default comparision function, which will be used if the user 
     97    -- hasn't specified a own comparision function. 
     98    default_compare a b = do 
     99        a' <- vCastRat a 
     100        b' <- vCastRat b 
     101        let cmp = if a' < b' then (-1) else if a' == b' then 0 else 1 
     102        return $ if min_or_max (cmp > (0::VInt)) then a else b 
    49103 
    50104op2FoldL :: Val -> Val -> Eval Val