代码之家  ›  专栏  ›  技术社区  ›  J Cooper

Haskell类定义中的隐式类型参数?

  •  4
  • J Cooper  · 技术社区  · 14 年前

    通常情况下,以下内容似乎是非法的:

    class Foo a where
        foo :: a -> b -> a
    

    这是有道理的,我们怎么知道 b 是?

    但是,如果我们看看函数的定义:

    class Functor f where
        fmap :: (a -> b) -> f a -> f b
    

    我们看到 a 即使我们只指定 f 作为类型变量。我猜这是允许的,因为编译器看到 f a 并且可以理解 f 它本身必须 所以使用它是安全的 在我们的函数定义中的其他地方。我说的对吗?

    2 回复  |  直到 14 年前
        1
  •  6
  •   Antal Spector-Zabusky    14 年前

    让我们分别看每一行。

    class Functor f where
    

    这声明了一个名为 Functor ;满足它的类型将被调用 f .

      fmap :: (a -> b) -> f a -> f b
    

    与任何函数定义一样,所有自由类型变量都是隐式的 forall Ed_可以用任何东西替换。不过,多亏了第一行, f 在范围之内。因此, fmap 具有类型签名 fmap :: forall a b. Functor f => (a -> b) -> f a -> f b . 换句话说,每个函数都需要定义 FMAP 哪个可以工作 任何 a b f 必须有 友善的 (类型的类型) * -> * ;也就是说,它必须是采用其他类型的类型,例如 [] Maybe IO .

    那么,你所说的是不正确的; 不是特别的,如果我们在 函子 ,看不到一样的东西 . 但是,编译器 使用 f a 有点想知道什么样的 f 必须是。此外,您的 Foo 类是完全合法的;我可以如下指定一个实例

    instance Foo (a -> b) where
      foo f _ = f
    

    这满足 foo :: a -> b -> a 对于 任何 请注意 在里面 Foo (a -> b) 是不同的。诚然,这不是一个很有趣的例子,但它是完全合法的。

        2
  •  3
  •   newacct    14 年前

    不需要“知道”。它只需要进行类型检查(即,没有失败的类型检查)。 b 可以是任何东西;功能 foo 必须能够将任何类型作为第二个参数。

    考虑一下 const 序曲中的功能:

    const            :: a -> b -> a
    const x _        =  x
    

    它如何“知道”什么 (或) a 是吗?