Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell类定义中的隐式类型参数?_Haskell_Type Inference_Typeclass - Fatal编程技术网

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

Haskell类定义中的隐式类型参数?,haskell,type-inference,typeclass,Haskell,Type Inference,Typeclass,通常情况下,以下行为似乎是非法的: class Foo a where foo :: a -> b -> a 这是有道理的;我们如何知道b是什么 但是,如果我们看函子的定义: class Functor f where fmap :: (a -> b) -> f a -> f b 我们看到出现了a和b,尽管我们只将f指定为类型变量。我猜这是允许的,因为编译器可以看到例如fa,并且可以计算出f本身必须取a,所以在我们的函子定义的其他地方使用a是安全

通常情况下,以下行为似乎是非法的:

class Foo a where
    foo :: a -> b -> a
这是有道理的;我们如何知道
b
是什么

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

class Functor f where
    fmap :: (a -> b) -> f a -> f b
我们看到出现了
a
b
,尽管我们只将
f
指定为类型变量。我猜这是允许的,因为编译器可以看到例如
fa
,并且可以计算出
f
本身必须取
a
,所以在我们的函子定义的其他地方使用
a
是安全的。我说的对吗?

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

考虑前奏曲中的
const
函数:

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

它是如何“知道”什么是
b
(或者
a
,就这一点而言)的呢?

让我们分别看看每一行

class Functor f where
这声明了一个名为
Functor
的单参数类型类;满足此条件的类型将被称为
f

  fmap :: (a -> b) -> f a -> f b
与任何函数定义一样,所有自由类型变量都是隐式的
forall
ed,它们可以被任何东西替换。但是,多亏了第一行,
f
在范围内。因此,
fmap
具有类型签名
fmap::forall a b。函子f=>(a->b)->f a->f b
。换句话说,每个函子都需要有一个
fmap
的定义,它可以用于任何
a
b
,而
f
必须有种类(类型的类型)
*->*
;也就是说,它必须是采用另一种类型的类型,例如
[]
可能
IO

那么,你所说的是不正确的;
a
并不特殊,如果我们在
Functor
中有另一个函数,它将不会看到相同的
a
b
。但是,编译器确实使用
fa
位来确定
f
必须是什么类型的。此外,你的
Foo
课程是完全合法的;我可以如下指定一个实例

instance Foo (a -> b) where
  foo f _ = f
这满足了任何
b
foo::a->b->a
;注意
Foo(a->b)
中的
b
是不同的。诚然,这不是一个很有趣的例子,但它是完全合法的