【问题标题】:Can I get this ambiguoulsly typed function to compile?我可以编译这个模棱两可的类型函数吗?
【发布时间】:2020-06-06 16:08:13
【问题描述】:

首先:我知道我不能使用这个功能,除非我启用了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
   |         ^

我知道,也许编译器无法将BF 实例与dh 的使用联系起来。我认为这样的事情可以解决这个问题:

m @p = h @p . d @p

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

是否有一些语言选项可供我选择,要么使类似的解决方法成为可能,要么完全使编译器能够推断连接?

【问题讨论】:

    标签: haskell types ambiguous


    【解决方案1】:

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

    {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
    
    m :: forall n o. (B n, F n) => o -> o
    m = h @n . d @n
    

    使用the ScopedTypeVariables extension 来引用类型签名中指定的类型n

    【讨论】:

    • 您只需要其中一个应用程序,将推断出另一个应用程序。
    【解决方案2】:

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

    m @p = ... 没有使用类型参数p 定义多态函数m;这种事情没有语法(使用ScopedTypeVariables的解决方案是最接近的近似值)。 m@p 是一个 as 模式,将两个变量 mp 绑定到相同的值。 @ 在其右组件是非平凡模式时更常用:

    t@(x, y) = somepair
    
    -- equivalent to --
    
    t = somepair
    (x, y) = t
    

    【讨论】:

      猜你喜欢
      • 2017-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-21
      • 1970-01-01
      • 2011-07-23
      相关资源
      最近更新 更多