zig*_*zou 1 haskell bounded-types
对于一个项目,我创建了一个基于Int的类型,只要程序试图使用超出限制的值(在我的情况下为[0..127])就会抛出错误.下面的代码执行此操作,它适用于我.
是否有可能在Haskell中创建第二个有界类型(例如[0..255])而不重复此代码?
谢谢你的回答
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Minitel.Type.MNatural (MNat, mnat, fromMNat) where
-- | The MNat type. The constructor is hidden.
newtype MNat = MakeMNat Int deriving (Real, Eq, Ord, Show)
-- | MNat is a bounded type
instance Bounded MNat where
minBound = MakeMNat 0
maxBound = MakeMNat 127
-- | Converts an Int into an MNat
mnat :: Int -> MNat
mnat x | loLimit <= x && x <= hiLimit = MakeMNat x
| otherwise = error "Number out of bounds"
where loLimit = fromIntegral (minBound :: MNat)
hiLimit = fromIntegral (maxBound :: MNat)
-- | Converts an MNat into an Int
fromMNat :: MNat -> Int
fromMNat (MakeMNat i) = i
-- | Converts an Int binary function returning Int to a MNat binary function
-- returning an MNat
mfnat :: (Int -> Int) -> (MNat -> MNat)
mfnat f = mnat . f . fromMNat
mfnat2 :: (Int -> Int -> Int) -> (MNat -> MNat -> MNat)
mfnat2 f x y = mnat $ f (fromMNat x) (fromMNat y)
-- | You can do additions, substractions and multiplication with MNat
instance Num MNat where
fromInteger = mnat . fromIntegral
(+) = mfnat2 (+)
(-) = mfnat2 (-)
(*) = mfnat2 (*)
abs = mfnat abs
signum = mfnat signum
-- | Allows to use toInteger with MNat
instance Integral MNat where
quotRem x y = (fromInteger $ quot x' y', fromInteger $ rem x' y')
where (x', y') = (toInteger x, toInteger y)
toInteger = toInteger . fromMNat
-- | Allows to generate lists
instance Enum MNat where
toEnum = mnat
fromEnum = fromMNat
Run Code Online (Sandbox Code Playgroud)
注意:
您可以使用类型级文字在GHC 7.8中执行此操作:
{-# LANGUAGE DataKinds, PolyKinds, ScopedTypeVariables #-}
module SO26723035 where
import GHC.TypeLits
import Data.Proxy
newtype MNat (n :: Nat) = MakeMNat Int deriving (Eq, Ord, Show)
instance KnownNat n => Bounded (MNat n) where
minBound = MakeMNat 0
maxBound = MakeMNat . fromInteger $ natVal (Proxy :: Proxy n)
Run Code Online (Sandbox Code Playgroud)
ghci> maxBound :: MNat 5
MakeMNat 5
Run Code Online (Sandbox Code Playgroud)
您可以使用类型同义词来修复单个类型.其余的代码可以MNat通过机械更改来编译这种多态.您必须添加KnownNat到处上下文和使用ScopedTypeVariables在mnat.