TypeLits或Singletons:在运行时将`Integer`提升为`KnownNat`(`Nat`)

时间:2017-10-15 01:59:14

标签: haskell types ghc dependent-type singleton-type

我发现有两种方法可以在运行时使用TypeLits和Proxy(Data.Proxy和GHC.TypeLits)或Singletons(或者Singletons)在运行时将Integer提升为Nat(或者KnownNat,我还没有得到区别)。 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的文档表明它不应该被开发人员使用,但是单身人士不会捕获给定的Integer不是自然数的情况(即,运行playingWithTypes 8运行没有错误,但是当我们尝试从非自然数创建一个Singleton时,playingWithTypes (-2)失败了。

那么,将Integer推广到Nat的“标准”方式是什么?或者,使用TypeLits和Proxy或Singletons进行推广的最佳方法是什么?

1 个答案:

答案 0 :(得分:7)

  

Nat(或KnownNat,我还没有得到区别)

Nat是一种类型级自然数。它没有任期级别的居民。这个想法是GHC将任何自然数字提升到类型级别,并赋予其类型Nat

KnownNat是一种约束,关于某种类Nat,它的实现见证了如何将类Nat的事物转换为术语级Integer。 GHC为所有类型级别居民KnownNat 1 自动创建Nat个实例。

也就是说,即使每个n :: Nat(类型n的读取类型Nat)上都有KnownNat个实例 1 ,仍然需要写出约束。

  

我找到了两种方法来推广IntegerNat

你真的吗?在一天结束时,Nat在今天的GHC中只是神奇的。 singletons使用同样的魔法。在引擎盖下,uses someNatVal

  

那么,将Integer推广到Nat的“标准”方式是什么?或者,使用GHC.TypeLitsProxy或单身人士推广的最佳方法是什么?

没有标准的方法。我的看法是:当你可以负担其依赖性足迹时使用singletons,否则使用GHC.TypeLitssingletons的优势在于,SingI类型类可以方便地进行基于归纳的分析,同时还依赖于GHC的特殊Nat类型。

1 正如评论中所指出的那样, Nat类的每个居民都没有KnownNat个实例。例如,Any Nat :: Nat其中Anyone from GHC.Exts。只有居民012,......才有KnownNat个实例。