
Dear Alexander, FWIW, this sort of thing is quite straightforward with LiquidHaskell: http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1418064183.hs or, the code below: ----- {-@ LIQUID "--no-termination" @-} module Nat255 where -- | Define a predicate for valid integers {-@ predicate IsValid X = 0 <= X && X < 255 @-} -- | Use the predicate to define a refinement type (subset) of valid integers {-@ type Valid = {v:Int | IsValid v} @-} -- | A function that checks whether a given Int is indeed valid {-@ isValid :: n:Int -> {v:Bool | Prop v <=> IsValid n} @-} isValid n = 0 <= n && n < (255 :: Int) -- | A function that can only be called with Valid Ints. {-@ workWithValidNumber :: Valid -> IO () @-} workWithValidNumber n = putStrLn $ "This is a valid number" ++ show (n :: Int) -- | This is fine... ok = workWithValidNumber 12 -- | ... But this is not. notOk = workWithValidNumber 257 -- | Finally the top level loop that inputs a number, tests it -- and calls `workWithValidNumber` if the number is valid. loop = do putStrLn "Enter Number between 0 and 255" n <- readLn :: IO Int if isValid n then workWithValidNumber n else putStrLn "Humph, bad input, try again!" >> loop