简体   繁体   中英

Why isn't there an interval typeclass in haskell?

Maybe I have not looked in the right place, but I could not find a type class for intervals in Haskell. It seems to me that this abstraction would be useful in many cases, since intervals are used in many domains.

This can also be seen in the amount of different packages on hackage that implement some sort of interval structure ( list of interval packages ).

Would it be to confusing to implement the different types of intervals (open, closed, ...) with type classes, or is there another concepts which helps me to build my own intervals except of an own data type?

You can do this with -XFunctionalDependences and -XFlexibleInstances (to write any instances with this...). I've written some code below with comments to illustrate:

{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}

-- | Intervals with endpoints of type e.
class (Ord e) => Interval i e | i -> e where
  {-# MINIMAL inf, sup #-}
  -- lower bound ("infinimum") 
  inf :: i -> e
  -- upper bound ("supremum")
  sup :: i -> e

-- Is (X : Interval e) a valid Interval?
valid :: Interval i e => i -> Bool
valid x = sup x > inf x

-- Is (X : Interval e) an invalid Interval?
notValid :: Interval i e => i -> Bool
notValid = not . valid

-- Is (x : e) contained within (X : Interval e)
containsPoint :: Interval i e => i -> e -> Bool
x `containsPoint` p = p >= inf x && p <= sup x

-- Is (x : e) below (X : Interval e)
abovePoint :: Interval i e => i -> e -> Bool
x `abovePoint` p = p < inf x

-- Is (x : e) above (X : Interval e)
belowPoint :: Interval i e => i -> e -> Bool
x `belowPoint` p = p > sup x

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x < y iff sup X < inf Y 
before :: Interval i e => i -> i -> Bool
x `before` y = sup x < inf y

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x > y iff inf X > sup Y 
after :: Interval i e => i -> i -> Bool
x `after` y = inf x > sup y

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x == y iff (inf X == inf Y) && (sup X == sup Y)
equals :: Interval i e => i -> i -> Bool
x `equals` y = inf x == inf y && sup x == sup y

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x /= y iff (sup x < inf y) || (inf x > sup y)
nequals :: Interval i e => i -> i -> Bool
x `nequals` y = sup x < inf y || inf x > sup y

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x <= y iff sup x <= inf y
eqBefore :: Interval i e => i -> i -> Bool
x `eqBefore` y = sup x <= inf y

-- For all (x : e) in (X : Interval e), (y : e) in (Y : Interval e),
-- x >= y iff inf x >= sup y
eqAfter :: Interval i e => i -> i -> Bool
x `eqAfter` y = inf x >= sup y

-- Does (X : Interval e) contain (Y : Interval e)?
contains :: Interval i e => i -> i -> Bool
x `contains` y = inf x <= inf y && sup y <= sup x

-- Is (X : Interval e) a subset of (Y : Interval e)?
isSubSetOf :: Interval i e => i -> i -> Bool
isSubSetOf = flip contains

-- Do (X : Interval e) and (Y : Interval e) overlap?
overlaps :: Interval i e => i -> i -> Bool 
x `overlaps` y = inf x <= sup y && sup x >= inf y

instance (Ord e) => Interval (e,e) e where
  inf (a,_) = a
  sup (_,b) = b

instance (Ord a) => Interval [a] a where
  inf = minimum
  sup = maximum

main :: IO ()
main = do
  putStrLn $ inf ["one","two","three"] -- will print "one"
  putStrLn $ sup ("first","second")    -- will print "second"

However, as commenters have pointed out, This is pretty unnecessary. It's probably better to have something like an Interval datatype and just have Interval Double , Interval Int , etc. I recommend the intervals package.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM