首先:我知道我不能使用这个函数,除非我有 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
| ^
我知道,也许编译器不能在GHCi 8.10.1和GHC 8.10.1之间建立连接 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
使用 的 ScopedTypeVariables
延长 指类型 n
类型签名中指定的。
为了补充实际的答案,您的尝试 (m @p = h @p . d @p
)没有编译,因为它使用的符号实际上具有完全不相关的含义。
m @p = ...
并没有定义一个多态函数。m
带类型参数的 p
;没有这样的语法(使用 ScopedTypeVariables
是最接近的近似值)。) m@p
是一个如模式,绑定两个变量 m
和 p
到相同的值。@
当它的右分量是一个非平凡模式时,更常用。
t@(x, y) = somepair
-- equivalent to --
t = somepair
(x, y) = t