Haskell 部分函数应用 $
Haskell partial function application with $
我是 Haskell 的新手,正在查看一个使用 $
函数应用程序的简单示例。
这看起来很简单 - 它接受一个函数并将其应用于一个值。
所以这是有道理的:
> (+3) $ 2
5
这也有道理:
> ($) (+3) 2
5
这是有道理的,因为第一个参数是函数,第二个参数是值。
现在考虑使用 $
创建偏函数。
查看类型,这是有道理的 - 它只需要 b
:
的 Num
类型值
> :t ($) (+3)
($) (+3) :: Num b => b -> b
但这就是我迷路的地方 - 这里发生了什么?:
> :t ($) (2)
($) (2) :: Num (a -> b) => a -> b
我原以为第一个参数需要是一个函数,而不是一个简单的 Num 值。
所以这是我的问题:
- 这里发生了什么?
- 约束
Num (a -> b)
语法是什么意思?
- 以这种方式使用
($)
的示例是什么,它以 ($) (2)
之类的内容开头?
谢谢!
一方面,像 2
这样的数字文字实际上被读作 fromInteger 2 :: Num a => a
,因此可以表示 Num a => a
类型的任何值,意思是 的任何类型]in 类型 class Num
,即除其他外,还有一个特殊版本的 fromInteger
定义了 returns 实际类型的实际值,从整数 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
正如 the Haskell Tutorial 所说(在 10.3 中),
An integer numeral (without a decimal point) is actually equivalent to an application of fromInteger
to the value of the numeral as an Integer
.
另一方面,($)
的类型是
> :t ($)
($) :: (a -> b) -> a -> b
所以我们有
fromInteger 2 :: Num a1 => a1
($) :: (a -> b) -> a -> b
--------------------------------------------
($) 2 :: Num (a -> b) => a -> b
所以它是一个函数,它也必须是在类型class Num
.
通常情况并非如此,但 Haskell 不知道您是否可以导入某个确实定义了此类实例的模块:
instance Num (a -> b) where
....
fromInteger n = ....
....
所以它在类型检查时允许这种可能性,只有到那时,看到没有在任何地方定义这样的实际实例,它才会在 that.[=29= 上出错]
例如,根据评论中@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)
让我们写(sin + 2 * cos^2) x
.
我是 Haskell 的新手,正在查看一个使用 $
函数应用程序的简单示例。
这看起来很简单 - 它接受一个函数并将其应用于一个值。
所以这是有道理的:
> (+3) $ 2
5
这也有道理:
> ($) (+3) 2
5
这是有道理的,因为第一个参数是函数,第二个参数是值。
现在考虑使用 $
创建偏函数。
查看类型,这是有道理的 - 它只需要 b
:
Num
类型值
> :t ($) (+3)
($) (+3) :: Num b => b -> b
但这就是我迷路的地方 - 这里发生了什么?:
> :t ($) (2)
($) (2) :: Num (a -> b) => a -> b
我原以为第一个参数需要是一个函数,而不是一个简单的 Num 值。
所以这是我的问题:
- 这里发生了什么?
- 约束
Num (a -> b)
语法是什么意思? - 以这种方式使用
($)
的示例是什么,它以($) (2)
之类的内容开头?
谢谢!
一方面,像 2
这样的数字文字实际上被读作 fromInteger 2 :: Num a => a
,因此可以表示 Num a => a
类型的任何值,意思是 的任何类型]in 类型 class Num
,即除其他外,还有一个特殊版本的 fromInteger
定义了 returns 实际类型的实际值,从整数 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
正如 the Haskell Tutorial 所说(在 10.3 中),
An integer numeral (without a decimal point) is actually equivalent to an application of
fromInteger
to the value of the numeral as anInteger
.
另一方面,($)
的类型是
> :t ($)
($) :: (a -> b) -> a -> b
所以我们有
fromInteger 2 :: Num a1 => a1
($) :: (a -> b) -> a -> b
--------------------------------------------
($) 2 :: Num (a -> b) => a -> b
所以它是一个函数,它也必须是在类型class Num
.
通常情况并非如此,但 Haskell 不知道您是否可以导入某个确实定义了此类实例的模块:
instance Num (a -> b) where
....
fromInteger n = ....
....
所以它在类型检查时允许这种可能性,只有到那时,看到没有在任何地方定义这样的实际实例,它才会在 that.[=29= 上出错]
例如,根据评论中@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)
让我们写(sin + 2 * cos^2) x
.