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
值的任何其他想法?