如何使用Data.Type.Natural的可键入实例

时间:2014-09-18 03:13:32

标签: haskell ghc existential-type

Data.Type.Natural刚刚添加了Typeable个实例,一个用于提升类型'Z,另一个用于'S。虽然在实践中这意味着每个Nat都是Typeable,但编译器似乎并不知道这一点。因此,我无法使用该实例(例如)显示Nat

{-# LANGUAGE ExistentialQuantification, DataKinds, PolyKinds, ScopedTypeVariables #-}
module Foo where

import Data.Constraint
import Data.Proxy
import Data.Type.Natural
import Data.Typeable

import Unsafe.Coerce

data Depth a = forall n . D (Proxy (n :: Nat))

getConstraint :: forall n . Proxy n -> Dict (Typeable n)
getConstraint _ = unsafeCoerce (Dict :: Dict ())

instance Show (Depth a) where
  show (D proxy) = 
    case getConstraint proxy of
      Dict -> show $ typeRep proxy

test :: Depth a -> Depth a -> Depth a
test (D (Proxy::Proxy n1)) (D (Proxy::Proxy n2)) = D (Proxy::Proxy (Max n1 n2))

main = print $ show $ test (D (Proxy::Proxy N0)) (D (Proxy::Proxy N1))

这在运行时因错误internal error: stg_ap_v_ret

而失败 理查德艾森伯格说:“unsafeCoerce Dict可用于满足this mailing list中的任意约束”。我在这里尝试了这个想法,但我的解决方案是触发GHC“bug”。然而,当我查看GHC trac时,我发现GHC is allowed to get angry如果unsafeCoerce使用不当,我怀疑这就是我所做的。

另一种方法是尝试从GADT获取约束:

{-# LANGUAGE ExistentialQuantification, DataKinds, PolyKinds, GADTs, ScopedTypeVariables #-}
module Foo where

import Data.Constraint
import Data.Proxy
import Data.Type.Natural
import Data.Typeable

import Unsafe.Coerce

data Depth :: (* -> *) where
  D :: forall n a . (Typeable n) => Proxy (n :: Nat) -> Depth a

instance Show (Depth a) where
  show (D proxy) = show $ typeRep proxy

test :: Depth a -> Depth a -> Depth a
test (D (Proxy::Proxy n1)) (D (Proxy::Proxy n2)) = D (Proxy::Proxy (Max n1 n2))

main = print $ show $ test (D (Proxy::Proxy N0)) (D (Proxy::Proxy N1))

test无法推断Typeable (Max n1 n2),我认为除了在其他解决方案中尝试的unsafeCoerce黑客之外,我没有任何办法让GHC推断出来。

在我的实际代码中,我正试图保留Depth种类* -> *,并使Nat类型存在量化。关于如何打印Nat中的Depth值的任何其他想法?

0 个答案:

没有答案