在SomeNat上通过模式匹配而产生的类型变量的范围是什么?

时间:2018-08-05 23:45:47

标签: haskell types existential-type type-level-computation

我无法理解为什么要使用此代码:

-- someNatVal test case
--
-- David Banas <capn.freako@gmail.com>
-- August 5, 2018

{-# OPTIONS_GHC -Wall #-}

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

import GHC.TypeLits
import Data.Proxy

tellNat :: forall n. KnownNat n => Integer
tellNat = natVal (Proxy :: Proxy n)

foo :: Integer -> Integer
foo n =
  let SomeNat (_ :: Proxy m) =
        fromMaybe (error "Negative Nat!") (someNatVal n)
   in tellNat @m

main :: IO ()
main = print $ foo 1 == 1

产生此编译错误:

  

[1之1]编译Main(someNatValTest.hs,   someNatValTest.o)

     

someNatValTest.hs:22:16:错误:不在范围内:输入变量“ m”

根据@Carl,此代码:

{-# OPTIONS_GHC -Wall #-}

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

import GHC.TypeLits
import Data.Maybe
import Data.Proxy

tellNat :: forall n. KnownNat n => Integer
tellNat = natVal (Proxy :: Proxy n)

foo :: Integer -> Integer
foo n =
  case n' of
    SomeNat (_ :: Proxy m) ->
      tellNat @m
  where n' = fromMaybe (error "Negative Nat!") (someNatVal n)

main :: IO ()
main = print $ foo 1 == 1

有效:

dca9047d694f:tmp a594349$ stack runghc someNatValTest.hs
True

1 个答案:

答案 0 :(得分:2)

有趣的是-如果您尝试类似的操作,GHC通常会告诉您其大脑爆炸了。我想在您的情况下,SomeNat只是存在的,不是真正的GADT,因此您不会收到有趣的错误消息。

无论如何,如果要访问隐藏在数据类型内部的类型,则需要将构造函数与case表达式而不是let匹配。