TypeLits 或 Singletons:在运行时将 `Integer` 提升为 `KnownNat` (`Nat`)
TypeLits or Singletons: Promoting an `Integer` to `KnownNat` (`Nat`) at Runtime
我找到了两种在运行时将 Integer 提升为 Nat(或 KnownNat,我还没有区分)的方法,要么使用 TypeLits 和 Proxy(Data.Proxy 和 GHC.TypeLits),或单例 (Data.Singletons)。在下面的代码中,您可以看到如何使用这两种方法:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import Prelude hiding (replicate)
import Data.Proxy (Proxy(Proxy))
import Data.Monoid ((<>))
import Data.Singletons (SomeSing(..), toSing)
import GHC.TypeLits
import Data.Singletons.TypeLits
import Data.Vector.Sized (Vector, replicate)
main :: IO ()
main = playingWithTypes 8
playingWithTypes :: Integer -> IO ()
playingWithTypes nn = do
case someNatVal nn of
Just (SomeNat (proxy :: Proxy n)) -> do
-- let (num :: Integer) = natVal proxy
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
Nothing -> putStrLn "There's no number, the integer was not a natural number"
case (toSing nn :: SomeSing Nat) of
SomeSing (SNat :: Sing n) -> do
-- let (num :: Integer) = natVal (Proxy :: Proxy n)
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
TypeLits 的文档表明开发人员不应使用它,但单例不会捕获给定整数不是自然数的情况(即 运行 playingWithTypes 8
运行没有错误,但是 playingWithTypes (-2)
当我们尝试从非自然数创建单例时失败)。
那么,将 Integer
提升为 Nat
的 "standard" 方法是什么?或者最好的推广方式是什么,使用 TypeLits 和 Proxy,还是 Singletons?
Nat
(or KnownNat
, I don't get the distintion yet)
Nat
是那种类型级别的自然数。它没有任期级别的居民。这个想法是 GHC 将任何自然数提升到类型级别,并赋予它类型 Nat
.
KnownNat
是一个约束,在某种事物 Nat
上,其实现见证了如何将事物 Nat
转换为术语级别 Integer
。 GHC 自动为 all 类型 Nat
1.[=52= 类型的居民创建 KnownNat
的实例]
也就是说,即使每个 n :: Nat
(读取类型 n
类型 Nat
)都有一个 KnownNat
实例1,你还需要写出约束条件。
I've found two ways to promote an Integer
to a Nat
你真的吗?归根结底,Nat
在今天的 GHC 中简直是神奇的。 singletons
利用了同样的魔法。在引擎盖下,它 uses someNatVal
.
So, what is the "standard" way to promote an Integer
to a Nat
? Or what is the best approach to promote, using GHC.TypeLits
and Proxy
, or singletons?
没有标准的方法。我的看法是:当你能负担得起它的依赖足迹时使用 singletons
,否则使用 GHC.TypeLits
。 singletons
的优点是 SingI
类型 class 可以方便地进行基于归纳的分析,同时仍然依赖于 GHC 的特殊 Nat
类型。
1 正如评论中指出的那样,并非 每个 Nat
类型的居民都有 KnownNat
实例。例如,Any Nat :: Nat
其中 Any
是 one from GHC.Exts
。只有居民0
、1
、2
、...有KnownNat
个实例。
我找到了两种在运行时将 Integer 提升为 Nat(或 KnownNat,我还没有区分)的方法,要么使用 TypeLits 和 Proxy(Data.Proxy 和 GHC.TypeLits),或单例 (Data.Singletons)。在下面的代码中,您可以看到如何使用这两种方法:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import Prelude hiding (replicate)
import Data.Proxy (Proxy(Proxy))
import Data.Monoid ((<>))
import Data.Singletons (SomeSing(..), toSing)
import GHC.TypeLits
import Data.Singletons.TypeLits
import Data.Vector.Sized (Vector, replicate)
main :: IO ()
main = playingWithTypes 8
playingWithTypes :: Integer -> IO ()
playingWithTypes nn = do
case someNatVal nn of
Just (SomeNat (proxy :: Proxy n)) -> do
-- let (num :: Integer) = natVal proxy
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
Nothing -> putStrLn "There's no number, the integer was not a natural number"
case (toSing nn :: SomeSing Nat) of
SomeSing (SNat :: Sing n) -> do
-- let (num :: Integer) = natVal (Proxy :: Proxy n)
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
TypeLits 的文档表明开发人员不应使用它,但单例不会捕获给定整数不是自然数的情况(即 运行 playingWithTypes 8
运行没有错误,但是 playingWithTypes (-2)
当我们尝试从非自然数创建单例时失败)。
那么,将 Integer
提升为 Nat
的 "standard" 方法是什么?或者最好的推广方式是什么,使用 TypeLits 和 Proxy,还是 Singletons?
Nat
(orKnownNat
, I don't get the distintion yet)
Nat
是那种类型级别的自然数。它没有任期级别的居民。这个想法是 GHC 将任何自然数提升到类型级别,并赋予它类型 Nat
.
KnownNat
是一个约束,在某种事物 Nat
上,其实现见证了如何将事物 Nat
转换为术语级别 Integer
。 GHC 自动为 all 类型 Nat
1.[=52= 类型的居民创建 KnownNat
的实例]
也就是说,即使每个 n :: Nat
(读取类型 n
类型 Nat
)都有一个 KnownNat
实例1,你还需要写出约束条件。
I've found two ways to promote an
Integer
to aNat
你真的吗?归根结底,Nat
在今天的 GHC 中简直是神奇的。 singletons
利用了同样的魔法。在引擎盖下,它 uses someNatVal
.
So, what is the "standard" way to promote an
Integer
to aNat
? Or what is the best approach to promote, usingGHC.TypeLits
andProxy
, or singletons?
没有标准的方法。我的看法是:当你能负担得起它的依赖足迹时使用 singletons
,否则使用 GHC.TypeLits
。 singletons
的优点是 SingI
类型 class 可以方便地进行基于归纳的分析,同时仍然依赖于 GHC 的特殊 Nat
类型。
1 正如评论中指出的那样,并非 每个 Nat
类型的居民都有 KnownNat
实例。例如,Any Nat :: Nat
其中 Any
是 one from GHC.Exts
。只有居民0
、1
、2
、...有KnownNat
个实例。