如何将newtype转换为Int,反之亦然?
我试过了:
newtype NT1 = NT1 Integer
fromNT1toInt :: NT1 -> Int
fromNT1toInt x = let y = x :: Int
in y
Run Code Online (Sandbox Code Playgroud)
但我得到的不能匹配预期的类型错误
我尝试制作Enum类的NT1实例,但我不太了解toEnum是如何工作的
newtype NT1 = NT1 Integer
instance Enum NT1 where
toEnum x = let x = x :: Integer
in if x >= 0
then x :: NT1
else x :: NT1
Run Code Online (Sandbox Code Playgroud)
当我调用Ennum 5 :: NT1这应该返回5 NT1但我得到StackOverflow错误.我哪里弄错了?
编辑:newtype名称
e :: t并不意味着"将表达式转换e为类型t",它只是一个注释,表示" e 有类型 t(已经)".所以这:
let y = x :: Int in y
Run Code Online (Sandbox Code Playgroud)
意思是:断言x有类型Int,设置y等于x,并返回y.这就是你输入类型不匹配的原因:x没有类型,Int因为你声称编译器.还有这个:
let x = x :: Integer
in if x >= 0 then x :: NT1 else x :: NT1
Run Code Online (Sandbox Code Playgroud)
意思是:声明一个新变量x,将它设置为等于它自己(一个无限循环),声明它有类型Integer,然后测试该无限循环是否返回一个非负值; 无论哪种方式,返回x,断言它有类型NT1(这与Integer之前的矛盾相反).
之间进行转换Integer并且Int,你可以使用fromIntegral :: (Integral a, Num b) => a -> b,其中任何整数类型(如转换Int或Integer)到任何数字类型(如Int,Integer,Float,Double,或Ratio).
要从newtypes 转换,您可以使用模式匹配:
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt (NT1 x) = fromIntegral x
Run Code Online (Sandbox Code Playgroud)
或者添加一个记录访问器功能newtype并使用:
newtype NT1 = NT1 { nt1Val :: Integer }
-- Note: nt1Val :: NT1 -> Integer
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt nt = fromIntegral (nt1Val nt)
-- Or, with function composition (.):
fromNT1ToInt = fromIntegral . nt1Val
Run Code Online (Sandbox Code Playgroud)
或者,最后,使用coerce来自Data.Coerce:
import Data.Coerce (coerce)
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt nt = fromIntegral (coerce nt :: Integer)
Run Code Online (Sandbox Code Playgroud)
当然,构建一个newtype你只需使用它的构造函数 - 在这种情况下NT1 :: Integer -> NT1,例如NT1 5.
用于fromIntegral在整数类型之间进行转换,例如Int和Integer。用于从toNT1转换,以及从to进行模式匹配。最后,您可以组合函数来连接事物。IntegerNT1NT1Integer
toNT1 :: Int -> NT1
toNT1 = NT1 . fromIntegral
fromNT1 :: NT1 -> Int
fromNT1 (NT1 x) = fromIntegral x
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
250 次 |
| 最近记录: |