如何将 newtype 转换为 Int,反之亦然?
我尝试过:
newtype NT1 = NT1 Integer
fromNT1toInt :: NT1 -> Int
fromNT1toInt x = let y = x :: Int
in y
但我得到无法匹配预期类型错误
我尝试制作 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
当我调用 toEnum 5::NT1 时,这应该返回 5 NT1 但我收到 StackOverflow 错误。 我哪里出错了?
编辑:新类型名称
最佳答案
e :: t
并不意味着“转换表达式 e
输入t
”,这只是一个注释,上面写着“e
有类型 t
(已经)”。所以这个:
let y = x :: Int in y
含义:断言 x
类型为Int
,设置y
等于 x
,然后返回y
。这就是类型不匹配的原因:x
没有类型 Int
正如您向编译器声称的那样。还有这个:
let x = x :: Integer
in if x >= 0 then x :: NT1 else x :: NT1
含义:声明一个新变量x
,将其设置为等于自身(无限循环),断言它的类型为 Integer
,然后测试该无限循环是否返回非负值;无论哪种方式,返回 x
,断言它的类型为 NT1
(这与之前的 Integer
相矛盾)。
在Integer
之间进行转换和Int
,您可以使用fromIntegral :: (Integral a, Num b) => a -> b
,它将任何整数类型(例如 Int
或 Integer
)转换为任何数值类型(例如 Int
、 Integer
、 Float
、 Double
或 Ratio
)。
用于从 newtype
进行转换s,您可以使用模式匹配:
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt (NT1 x) = fromIntegral x
或者向 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
或者,最后,使用coerce
来自Data.Coerce
:
import Data.Coerce (coerce)
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt nt = fromIntegral (coerce nt :: Integer)
当然,要构造一个 newtype
您只需使用它的构造函数 - 在本例中为 NT1 :: Integer -> NT1
,例如NT1 5
.
关于haskell - 从 newtype 转换为 Int 以及从 Int 转换为 newtype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53273610/