我可以编译这个类型不明确的函数吗?
Can I get this ambiguoulsly typed function to compile?
首先:我知道我无法使用此功能,除非我启用了 TypeApplications
。但我认为 AllowAmbiguousTypes
是为了解决这个问题。
我目前有以下代码:
{-# LANGUAGE ExplicitForAll, AllowAmbiguousTypes #-}
module A where
class B c where
d :: forall e. e -> c e
class F g where
h :: forall i. g i -> i
data J k = J {l :: k}
instance B J where
d = J
instance F J where
h = l
m :: forall n o. (B n, F n) => o -> o
m = h . d
用 GHCi 8.10.1 解释它或用 GHC 8.10.1 编译它会导致这个错误:
j.hs:20:5: error:
• Could not deduce (F g0) arising from a use of ‘h’
from the context: (B n, F n)
bound by the type signature for:
m :: forall (n :: * -> *) o. (B n, F n) => o -> o
at j.hs:19:1-37
The type variable ‘g0’ is ambiguous
These potential instance exist:
instance F J -- Defined at j.hs:16:10
• In the first argument of ‘(.)’, namely ‘h’
In the expression: h . d
In an equation for ‘m’: m = h . d
|
20 | m = h . d
| ^
j.hs:20:9: error:
• Could not deduce (B g0) arising from a use of ‘d’
from the context: (B n, F n)
bound by the type signature for:
m :: forall (n :: * -> *) o. (B n, F n) => o -> o
at j.hs:19:1-37
The type variable ‘g0’ is ambiguous
These potential instance exist:
instance B J -- Defined at j.hs:13:10
• In the second argument of ‘(.)’, namely ‘d’
In the expression: h . d
In an equation for ‘m’: m = h . d
|
20 | m = h . d
| ^
我的理解是,编译器可能无法将 B
和 F
实例与 d
和 h
的用法联系起来。我认为这样的事情可以解决这个问题:
m @p = h @p . d @p
但是,即使使用TypeApplications
,也被拒绝了。
是否有某种语言选项可供我选择,使类似的解决方法成为可能或完全使编译器能够推断出连接?
您的想法是正确的,但是没有现有的方法可以在等式的左侧绑定类型参数。 (正在进行将其添加为扩展的工作,但它已 运行 进入一些需要解决的边缘情况。)但是由于它是带有附加类型签名的顶级定义,您可以只使用那里的类型:
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
m :: forall n o. (B n, F n) => o -> o
m = h @n . d @n
使用 the ScopedTypeVariables
extension 来引用类型签名中指定的类型 n
。
为了补充实际答案,您的尝试 (m @p = h @p . d @p
) 未通过编译,因为它使用的符号实际上具有完全不相关的含义。
m @p = ...
没有定义带有类型参数 p
的多态函数 m
;这种事情没有语法(使用 ScopedTypeVariables
的解决方案是最接近的近似值)。 m@p
是一个 as-pattern,将两个变量 m
和 p
绑定到同一个值。当 @
的右侧组件是一个非平凡的模式时更常用:
t@(x, y) = somepair
-- equivalent to --
t = somepair
(x, y) = t
首先:我知道我无法使用此功能,除非我启用了 TypeApplications
。但我认为 AllowAmbiguousTypes
是为了解决这个问题。
我目前有以下代码:
{-# LANGUAGE ExplicitForAll, AllowAmbiguousTypes #-}
module A where
class B c where
d :: forall e. e -> c e
class F g where
h :: forall i. g i -> i
data J k = J {l :: k}
instance B J where
d = J
instance F J where
h = l
m :: forall n o. (B n, F n) => o -> o
m = h . d
用 GHCi 8.10.1 解释它或用 GHC 8.10.1 编译它会导致这个错误:
j.hs:20:5: error:
• Could not deduce (F g0) arising from a use of ‘h’
from the context: (B n, F n)
bound by the type signature for:
m :: forall (n :: * -> *) o. (B n, F n) => o -> o
at j.hs:19:1-37
The type variable ‘g0’ is ambiguous
These potential instance exist:
instance F J -- Defined at j.hs:16:10
• In the first argument of ‘(.)’, namely ‘h’
In the expression: h . d
In an equation for ‘m’: m = h . d
|
20 | m = h . d
| ^
j.hs:20:9: error:
• Could not deduce (B g0) arising from a use of ‘d’
from the context: (B n, F n)
bound by the type signature for:
m :: forall (n :: * -> *) o. (B n, F n) => o -> o
at j.hs:19:1-37
The type variable ‘g0’ is ambiguous
These potential instance exist:
instance B J -- Defined at j.hs:13:10
• In the second argument of ‘(.)’, namely ‘d’
In the expression: h . d
In an equation for ‘m’: m = h . d
|
20 | m = h . d
| ^
我的理解是,编译器可能无法将 B
和 F
实例与 d
和 h
的用法联系起来。我认为这样的事情可以解决这个问题:
m @p = h @p . d @p
但是,即使使用TypeApplications
,也被拒绝了。
是否有某种语言选项可供我选择,使类似的解决方法成为可能或完全使编译器能够推断出连接?
您的想法是正确的,但是没有现有的方法可以在等式的左侧绑定类型参数。 (正在进行将其添加为扩展的工作,但它已 运行 进入一些需要解决的边缘情况。)但是由于它是带有附加类型签名的顶级定义,您可以只使用那里的类型:
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
m :: forall n o. (B n, F n) => o -> o
m = h @n . d @n
使用 the ScopedTypeVariables
extension 来引用类型签名中指定的类型 n
。
为了补充实际答案,您的尝试 (m @p = h @p . d @p
) 未通过编译,因为它使用的符号实际上具有完全不相关的含义。
m @p = ...
没有定义带有类型参数 p
的多态函数 m
;这种事情没有语法(使用 ScopedTypeVariables
的解决方案是最接近的近似值)。 m@p
是一个 as-pattern,将两个变量 m
和 p
绑定到同一个值。当 @
的右侧组件是一个非平凡的模式时更常用:
t@(x, y) = somepair
-- equivalent to --
t = somepair
(x, y) = t