Haskell初学者查询

Haskell初学者查询,haskell,Haskell,嗨,我有一个关于简单haskell定义的问题。我有一个定义,但我不完全理解它 该函数接收函数和项的列表,并返回应用该函数形成的列表 applyAll=\fs->\x->map(\n->nx)fs 有人能解释一下n是做什么的,为什么fs在map函数之外吗 间距会误导您。看起来map(\n->nx)是一个函数调用,但是这里的括号是用于分组的,不是函数调用map接受两个参数;完整调用是map(\n->nx)fs,其中(\n->nx)是第一个参数(lambda表达式),而fs是第二个参数 lambda\

嗨,我有一个关于简单haskell定义的问题。我有一个定义,但我不完全理解它

该函数接收函数和项的列表,并返回应用该函数形成的列表

applyAll=\fs->\x->map(\n->nx)fs


有人能解释一下n是做什么的,为什么fs在map函数之外吗

间距会误导您。看起来
map(\n->nx)
是一个函数调用,但是这里的括号是用于分组的,不是函数调用
map
接受两个参数;完整调用是
map(\n->nx)fs
,其中
(\n->nx)
是第一个参数(lambda表达式),而
fs
是第二个参数


lambda
\n->nx
是一个函数,它将函数作为参数,并返回将该函数应用于
x
的结果
n
是这里的参数。
\n->nx
的类型是
(a->b)->b
(其中
a
x
的类型)。如果您已经了解了部分,lambda相当于部分
($x)
。如果没有,请忽略最后一句。

空格会误导您。看起来
map(\n->nx)
是一个函数调用,但是这里的括号是用于分组的,不是函数调用
map
接受两个参数;完整调用是
map(\n->nx)fs
,其中
(\n->nx)
是第一个参数(lambda表达式),而
fs
是第二个参数


lambda
\n->nx
是一个函数,它将函数作为参数,并返回将该函数应用于
x
的结果
n
是这里的参数。
\n->nx
的类型是
(a->b)->b
(其中
a
x
的类型)。如果您已经了解了部分,lambda相当于部分
($x)
。如果没有,请忽略最后一句。

这里有一个简单的函数定义:

f x = 2*x + 1
这将创建一个新函数
f
,该函数接受一个参数。以后您可以像这样使用它:

main = print (f 3)
applyAll fs x = map applyToX fs where
    applyToX n = n x
…将打印7。有时,定义一个函数而不给它命名是很方便的。它的语法是
\{-argument-}->{-function body-}
;例如,我们可以通过以下方式执行
f
的匿名版本:

main = print ((\x -> 2*x + 1) 3)
现在,您对
applyAll
的定义只做了几次。如果需要,我们可以在
where
子句中明确命名所有内容:

applyAll = outerMost where
    outerMost fs = mapApply where
         mapApply x = map applyToX fs where
             applyToX n = n x
…虽然我想你会同意,额外的罗嗦并不能让事情变得更清楚!对于匿名函数,更自然(但不那么机械)的翻译如下:

main = print (f 3)
applyAll fs x = map applyToX fs where
    applyToX n = n x

现在,希望这可以像英语一样理解:要将所有函数
fs
应用于单个值
x
,我们将“应用单个函数的函数(我们暂时命名为
n
)映射到所有函数列表上的值
x

下面是一个简单的函数定义:

f x = 2*x + 1
这将创建一个新函数
f
,该函数接受一个参数。以后您可以像这样使用它:

main = print (f 3)
applyAll fs x = map applyToX fs where
    applyToX n = n x
…将打印7。有时,定义一个函数而不给它命名是很方便的。它的语法是
\{-argument-}->{-function body-}
;例如,我们可以通过以下方式执行
f
的匿名版本:

main = print ((\x -> 2*x + 1) 3)
现在,您对
applyAll
的定义只做了几次。如果需要,我们可以在
where
子句中明确命名所有内容:

applyAll = outerMost where
    outerMost fs = mapApply where
         mapApply x = map applyToX fs where
             applyToX n = n x
…虽然我想你会同意,额外的罗嗦并不能让事情变得更清楚!对于匿名函数,更自然(但不那么机械)的翻译如下:

main = print (f 3)
applyAll fs x = map applyToX fs where
    applyToX n = n x

现在希望这可以像英语一样理解:要将所有函数应用于单个值
fs
,我们在所有函数列表中将“应用单个函数的函数(我们暂时命名为
n
)映射到值
x
”。

函数定义:

applyAll = \fs -> \x -> map(\n -> n x) fs
同:

applyAll fs x = map(\n -> n x) fs
现在你可能会问,“如果这些
->
只是我的函数
applyAll
的参数,它们在那里做什么?”。Haskell没有多参数函数的概念。一个函数的多个参数就是多个函数,每个函数都用一个参数链接在一起。对于
applyAll
,它只是两个链接在一起的函数:

(applyAll fs) -> x = map (\n -> n x) fs
applyAll fs
是将一个函数链接到另一个标识为
x
的参数,以生成由
map
返回的值列表

我可以在ghci中尝试:

Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs

<interactive>:1:10: Not in scope: `xs'
Prelude> let xs = [1..5] 
-- hah, BOOM! I told you haskell's strongly typed... 
Prelude> :t applyAll xs

<interactive>:1:10:
    Couldn't match expected type `t0 -> b0' with actual type `Integer'
    Expected type: [t0 -> b0]
      Actual type: [Integer]
    In the first argument of `applyAll', namely `xs'
    In the expression: applyAll xs
Prelude> let xs = [(1 +), (2 +), (3 *), (4 /)]
Prelude> :t xs
xs :: [Double -> Double]
Prelude> :t applyAll xs
applyAll xs :: Double -> [Double]
Prelude> :t applyAll
applyAll :: [t -> b] -> t -> [b]
Prelude> :t applyAll xs 3
applyAll xs 3 :: [Double]
Prelude> applyAll xs 3
[4.0,5.0,9.0,1.3333333333333333]
这告诉我,
map
接受一个函数——我们称它为
f
和一个值列表来返回另一个值列表。函数
f
是一个接受类型
a
的值并返回另一个类型
b
的值的函数。因此
map
继续将
f
应用于列表
[a]
中的每个值,以返回另一个填充了
b
类型值的列表


applyAll
中,函数
f
\n->nx
。这是一个lambda表达式(您可以称之为匿名函数),它接受由
n
标识的值,并对其应用
x
。对于类型定义中由
[a]
标识的输入列表中的每一项,都会继续执行此操作,直到它用完时生成类型定义中由
[b]
标识的另一个列表

函数定义:

applyAll = \fs -> \x -> map(\n -> n x) fs
同:

applyAll fs x = map(\n -> n x) fs
现在你可能会问,“如果那些
->
只是我的函数
applyAll
的参数,那么它们在那里做什么呢?”Haskell没有多参数函数的概念。你所看到的函数的多个参数就是多个函数