How can I create a numerical type with a range limit?

Asked 2 years ago, Updated 2 years ago, 104 views

I'd like to make a model like Int that limits the range with Haskell.
The following instances of the bounded class are not restricted:
How can I create a type like Int with a range limit?

 {-#LANGUAGE GeneralizedNewtypeDeriving#-}

newtype Century=Century Int
   deriving (Num, Eq, Ord, Show)

instance Boundary Century where
    minBound = 0
    maxBound = 100

haskell

2022-09-30 21:20

2 Answers

You can write your own Num class's fromInteger method and use numeric literals (base is similar to Hideki's answer).

 {-#LANGUAGE GeneralizedNewtypeDeriving#-}

module Century (Century, makeCentury) where

newtype Century=Century Int
    deriving (Eq, Ord, Show)

makeCentury::Int->Century
makeCenturyn
    | n<0||n>100 = error "Out of range"
    | otherwise=Centuryn

instance Num Century where
  Century a+Century b=makeCentury$a+b
  Century a*Century b=makeCentury$a*b
  abs(Centurya) = makeCentury$absa
  signum(Centurya) = makeCentury$signuma
  fromInteger=makeCentury.fromIntegral
  negate(Century a) = makeCentury$ negate a
*Century>1:Century
Century1
*Century > 100::Century
Century 100
*Century>10*100::Century
Century ***Exception: Out of range

However, please note that this code does not warn you of wraparound.


2022-09-30 21:20

In a nutshell, you can do something similar by hiding the definition of a type in a module and exporting a function that generates and returns values for that type.

For example, create Century.hs with the following contents:

 {-#LANGUAGE GeneralizedNewtypeDeriving#-}

module Century (makeCentury) where

newtype Century=Century Int
    deriving (Num, Eq, Ord, Show)

makeCentury::Int->Century
makeCenturyn
    | n<0||n>100 = error "Out of range"
    | otherwise=Centuryn

If you compile and import this, you will not be able to use the data constructor because Century has not been exported.

import Century

main ::IO()
main=do
    putStrLn$show(makeCentury3)--'Century3' output
    putStrLn$show(makeCentury101) -- Runtime Error
    -- putStrLn$show(Century1010) Unable to compile


2022-09-30 21:20

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.