我注意到 GHC 的 ScopedTypeVariables 能够在函数模式中绑定类型变量,但不能在 let 模式中绑定。
举个最简单的例子,考虑以下类型:
但是使用这个技巧将类型变量绑定到函数调用上时,它可以正常工作:
举个最简单的例子,考虑以下类型:
data Foo where Foo :: Typeable a => a -> Foo
如果我想访问Foo内部的类型,则以下方法无法编译:
fooType :: Foo -> TypeRep
fooType (Foo x) =
let (_ :: a) = x
in typeRep (Proxy::Proxy a)
但是使用这个技巧将类型变量绑定到函数调用上时,它可以正常工作:
fooType (Foo x) =
let helper (_ :: a) = typeRep (Proxy::Proxy a)
in helper x
由于let
绑定实际上是伪装成函数绑定的,那么为什么上面两个代码片段不等价呢?
(在此示例中,其他解决方案是使用typeOf x
创建TypeRep
,或者在顶级函数中直接将变量绑定为x :: a
。这两种选项都不适用于我的真实代码,并且使用它们不能回答问题。)
fooType (Foo x) = typeRep [x]
也可以工作,利用typeRep
的proxy
可以是任何函子的事实:不一定是平凡的Proxy
,它也可以是实际包含a
值的东西! - leftaroundaboutfooType (Foo x) =typeOf x
。我假设真正的用例是需要访问类型变量的重要部分。 - CarltypeOf
或其他解决方案(请参见括号中问题的最后一段),但在我的真实代码中却不可用。我需要通过将类型变量放入类型引用中来获取Template HaskellType
。我也不能直接在顶层函数中绑定a
,因为我正在尝试获取的类型实际上是隐藏类型的功能依赖项。辅助函数解决方案很好用,只是我真的不明白为什么。 - Theelepellet
不能做到这一点,因为它使用惰性模式匹配,而且无法将类型类字典引入作用域。这是与https://dev59.com/iGAg5IYBdhLWcg3wfrAn#23540431相同的问题。 - chi