How do I convert newtype to Int and vice versa?
I tried:
newtype NT1 = NT1 Integer
fromNT1toInt :: NT1 -> Int
fromNT1toInt x = let y = x :: Int
in y
but I get could't match expected type error
I tried making NT1 instance of Enum class but I don't understand well how does toEnum work
newtype NT1 = NT1 Integer
instance Enum NT1 where
toEnum x = let x = x :: Integer
in if x >= 0
then x :: NT1
else x :: NT1
when I call toEnum 5 :: NT1 this should return 5 NT1 but I get StackOverflow error. Where am I making mistake?
Edited: newtype name
e :: t doesn’t mean “convert expression e to type t”, it’s just an annotation that says “e has type t (already)”. So this:
let y = x :: Int in y
Means: assert that x has type Int, set y equal to x, and return y. That’s why you got a type mismatch: x does not have type Int as you are claiming to the compiler. And this:
let x = x :: Integer
in if x >= 0 then x :: NT1 else x :: NT1
Means: declare a new variable x, set it equal to itself (an infinite loop), asserting that it has type Integer, then test whether that infinite loop returns a nonnegative value; either way, return x, asserting that it has type NT1 (this contradicts the Integer from before).
To convert between Integer and Int, you can use fromIntegral :: (Integral a, Num b) => a -> b, which converts any integral type (such as Int or Integer) into any numeric type (such as Int, Integer, Float, Double, or Ratio).
For converting from newtypes, you can use pattern-matching:
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt (NT1 x) = fromIntegral x
Or add a record accessor function to the newtype and use that:
newtype NT1 = NT1 { nt1Val :: Integer }
-- Note: nt1Val :: NT1 -> Integer
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt nt = fromIntegral (nt1Val nt)
-- Or, with function composition (.):
fromNT1ToInt = fromIntegral . nt1Val
Or, finally, use coerce from Data.Coerce:
import Data.Coerce (coerce)
fromNT1ToInt :: NT1 -> Int
fromNT1ToInt nt = fromIntegral (coerce nt :: Integer)
And of course, to construct a newtype you just use its constructor—in this case, NT1 :: Integer -> NT1, e.g. NT1 5.
Use fromIntegral to convert between integral types, such as Int and Integer. Use NT1 to convert from Integer to NT1, and pattern-matching from NT1 to Integer. Finally, you can compose functions to connect things.
toNT1 :: Int -> NT1
toNT1 = NT1 . fromIntegral
fromNT1 :: NT1 -> Int
fromNT1 (NT1 x) = fromIntegral x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With