我可以编译这个模棱两可的类型函数吗?

sch*_*ine 3 haskell types ambiguous

首先:我知道我将无法使用此功能,除非我已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
Run Code Online (Sandbox Code Playgroud)

用 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
   |         ^
Run Code Online (Sandbox Code Playgroud)

我的理解是,也许,编译器不能得出之间的连接BF实例和用途dh。我认为这样的事情可以解决这个问题:

m @p = h @p . d @p

但是,即使使用TypeApplications,这也被拒绝。

是否有一些我可以选择的语言选项可以使类似的解决方法成为可能,或者直接使编译器能够推断出连接?

Car*_*arl 7

您的想法是正确的,但是没有现有的方法可以在等式的左侧绑定类型参数。(正在进行将其添加为扩展的工作,但它遇到了一些需要解决的边缘情况。)但是由于它是带有附加类型签名的顶级定义,因此您可以使用在那里输入:

{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}

m :: forall n o. (B n, F n) => o -> o
m = h @n . d @n
Run Code Online (Sandbox Code Playgroud)

使用ScopedTypeVariables扩展来引用类型n中的类型指定的签名。

  • 您只需要其中一个应用程序,系统就会推断出另一个应用程序。 (2认同)

Li-*_*Xia 5

为了补充实际答案,您的尝试 ( m @p = h @p . d @p) 没有编译,因为它使用的符号实际上具有完全不相关的含义。

m @p = ...没有定义m带有类型参数的多态函数p;这种事情没有语法(并且使用的解决方案ScopedTypeVariables是最接近的近似值)。m@p是作为图案,结合两个变量mp为相同的值。@当其正确的组件是一个非平凡的模式时,更常用:

t@(x, y) = somepair

-- equivalent to --

t = somepair
(x, y) = t
Run Code Online (Sandbox Code Playgroud)