Haskell部分函数应用程序用$

Kev*_*ard 4 polymorphism haskell types partial-application parametric-polymorphism

我是Haskell的新手,看一个使用函数应用程序的简单例子$.

它似乎很简单 - 它需要一个函数并将其应用于一个值.

所以这是有道理的:

> (+3) $ 2
5
Run Code Online (Sandbox Code Playgroud)

这也是有道理的:

> ($) (+3) 2
5
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为第一个参数是函数,第二个参数是值.

现在考虑使用$创建部分功能.

查看类型,这是有道理的 - 它只需要一个Num类型值b:

> :t ($) (+3)
($) (+3) :: Num b => b -> b
Run Code Online (Sandbox Code Playgroud)

但是这里我迷路了 - 这里发生了什么?:

> :t ($) (2)
($) (2) :: Num (a -> b) => a -> b
Run Code Online (Sandbox Code Playgroud)

我原以为第一个参数需要是一个函数,而不是一个简单的Num值.

所以这是我的问题:

  1. 这里发生了什么事?
  2. 约束Num (a -> b)语法是什么意思?
  3. ($)以这种方式使用的例子是什么($) (2)

谢谢!

Wil*_*ess 9

在一方面,数字文字就像2实际上读作fromInteger 2 :: Num a => a这样可以表示类型的任何值Num a => a,这意味着,任何类型,是类型的类Num,即除其他外有一个特殊版本的fromInteger定义返回的实际类型的实际值,从整数转换而来2:

> :i Num
class Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
Run Code Online (Sandbox Code Playgroud)

正如Haskell教程所说(在10.3中),

整数(不带小数点)实际上等同于fromInteger数字值的应用Integer.

另一方面,($)有类型

> :t ($)
($) :: (a -> b) -> a -> b
Run Code Online (Sandbox Code Playgroud)

所以我们有

fromInteger 2 :: Num a1 =>   a1
($)           ::          (a -> b) -> a -> b
--------------------------------------------
($) 2         :: Num      (a -> b) => a -> b
Run Code Online (Sandbox Code Playgroud)

所以它是一个函数,它也必须类型类中Num.

通常情况并非如此,但Haskell不知道您是否可以导入一些确定此类实例的模块:

instance Num (a -> b) where
   ....
   fromInteger n = ....
   ....
Run Code Online (Sandbox Code Playgroud)

因此它允许这种可能性的类型检查,也只有这样,看到有定义的任何地方没有这样的实际情况下,它的错误出在.

例如,根据评论中@augustss的提示,

instance (Num b) => Num (a -> b) where
   (+) f g x = f x + g x
   (*) f g x = f x * g x
   abs f x = abs (f x)
   negate f x = negate (f x)
   signum f x = signum (f x)
   fromInteger n = const (fromInteger n)
Run Code Online (Sandbox Code Playgroud)

让我们写(sin + 2 * cos^2) x.

  • 试试吧.:)你将能够写出像(sin + 2*cos)x`而不是`sin x + 2*cos x`这样的东西.编写实例声明并不难.这些类型将迫使您进行正确的定义. (2认同)