将类型族调用中的Nat转换为Integer

时间:2017-06-10 04:22:00

标签: 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)

失败
• 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)

我该如何解决?

1 个答案:

答案 0 :(得分:3)

您的代码存在两个问题。首先,(sing :: Sing n)在范围内没有n。您需要明确forall才能将其纳入范围。

其次,如果你想要SingI,你需要说出来。 GHC不知道并永远不会检查所有N t的{​​{1}}是SingI,这实际上并非如此:tN Bool但是Nat没有SingI (N Bool)

因此,解决方案:

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

或者使用类型应用程序:

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