Haskell 将Nat从类型族调用转换为整数

Haskell 将Nat从类型族调用转换为整数,haskell,Haskell,失败于 import Data.Singletons import Data.Singletons.TypeLits type family N t :: Nat where N Int = 42 N String = 9 foo :: (n ~ N t) => t -> Integer foo _ = fromSing (sing :: Sing n) 如何修复它?您的代码有两个问题。首先,(sing::sing n)在作用域中没有n。您需要显式地forall将其纳入

失败于

import Data.Singletons
import Data.Singletons.TypeLits

type family N t :: Nat where
  N Int = 42
  N String = 9

foo :: (n ~ N t) => t -> Integer
foo _ = fromSing (sing :: Sing n)

如何修复它?

您的代码有两个问题。首先,
(sing::sing n)
在作用域中没有
n
。您需要显式地
forall
将其纳入范围

第二,如果你想唱歌,你需要这样说。GHC不知道也从不检查所有
t
nt
是否为
SingI
,顺便说一句,这实际上不是真的:
N Bool
有种类
Nat
,但没有
SingI(N Bool)

因此,解决方案是:

• Could not deduce: DemoteRep * ~ Integer
  from the context: n ~ N t
    bound by the type signature for:
               foo :: n ~ N t => t -> Integer
    at mini.hs:16:1-32
• In the expression: fromSing (sing :: Sing n)
  In an equation for ‘foo’: foo _ = fromSing (sing :: Sing n)
或使用类型应用程序:

foo :: forall t. SingI (N t) => t -> Integer
foo _ = fromSing (sing :: Sing (N t))

谢谢,安德拉斯。现在有道理了。我不明白的是错误信息。ghc不应该抱怨n在Sing n中未绑定吗?@BrunoMartinez ghc将未绑定的类型变量视为上下文中的新变量,并允许您在以后的类型注释中引用它们。因此,它认为
n
Sing n
一个与
foo
签名中的
n
无关的新变量。
foo :: forall t. SingI (N t) => t -> Integer
foo _ = fromSing (sing @_ @(N t))