Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/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_Pointfree - Fatal编程技术网

Haskell 为什么不是';是否需要在此函数中提供参数?

Haskell 为什么不是';是否需要在此函数中提供参数?,haskell,pointfree,Haskell,Pointfree,我是Haskell的新手,本周我在几张幻灯片中发现了这个特殊的功能。我试图理解为什么以下函数不需要包含参数: -- Return all final segments of the argument, longest first -- (horrible runtime complexity, used here for illustration purposes only) tails :: [a] -> [[a]] tails = reverse . map reverse . in

我是Haskell的新手,本周我在几张幻灯片中发现了这个特殊的功能。我试图理解为什么以下函数不需要包含参数:

-- Return all final segments of the argument, longest first 
-- (horrible runtime complexity, used here for illustration purposes only)
tails :: [a] -> [[a]]
tails = reverse . map reverse . inits . reverse

如果我像
tails“thisisastring”
那样调用它,那么这将是一个有效的参数。是否需要提供一个参数,例如
tails xs=…
。我以前看到的所有其他函数都是这样的。

参数是隐式的。或者换一种说法,
相反。地图倒过来。初始化。反向
计算为类型为
[a]->[[a]]]
的函数

考虑一个更简单的例子:

double_impl x = x * 2
double = double_impl
此处的
double
的类型与
double\u impl
的类型相同,即它采用一个参数typeclass
Num

main = do 
  print $ double_impl 5
  print $ double 5

-- Out: 10
-- Out: 10

该参数是隐式的。或者换一种说法,
相反。地图倒过来。初始化。反向
计算为类型为
[a]->[[a]]]
的函数

考虑一个更简单的例子:

double_impl x = x * 2
double = double_impl
此处的
double
的类型与
double\u impl
的类型相同,即它采用一个参数typeclass
Num

main = do 
  print $ double_impl 5
  print $ double 5

-- Out: 10
-- Out: 10

通过检查
tails
的类型,我们可以看到它是一个函数

为了计算它的类型,我们首先写下组合中所有中间函数的类型。请注意,我们对函数的每次出现都使用新的类型变量

reverse :: [a] -> [a]
inits :: [b] -> [[b]]
map :: (c -> d) -> [c] -> [d]
现在我们有了
map reverse
has type
[[e]]->[[e]]]
,因为我们通过比较表达式得到了一些类型
e
c=d=[e]

reverse :: c -> d  -- for some c and d
reverse :: [e] -> [e] -- for some e
因此,最后两种中间体具有不同的类型

map reverse :: [[e]] -> [[e]]
reverse :: [f] -> [f]
现在我们开始尝试匹配类型。首先我要强调的是,这些显然不是真正的类型!(很抱歉所有的帽子,但我不想让任何人错过。)

下一篇作文:

map reverse . inits . reverse :: [a] -*- [[a]] = [[e]] -*> [[e]]
-- again, we have [[a]] = [[e]], so e = a, and we have
map reverse . inits . reverse :: [a] -> [[a]]
最后,我们有

reverse . map reverse . inits . reverse :: [a] -*- [[a]] = [f] -*> [f]
-- This time we have [[a]] = [f], so we must have f = [a], so the type
-- of the final composition is
tails = reverse . map reverse . inits . reverse :: [a] -> [[a]]

由于
tails
的类型为
[a]->[[a]]
,因此它必须是一个函数,它接受
a
s列表作为参数,并返回
a
s列表。

通过检查其类型,我们可以看出
tails
是一个函数

为了计算它的类型,我们首先写下组合中所有中间函数的类型。请注意,我们对函数的每次出现都使用新的类型变量

reverse :: [a] -> [a]
inits :: [b] -> [[b]]
map :: (c -> d) -> [c] -> [d]
现在我们有了
map reverse
has type
[[e]]->[[e]]]
,因为我们通过比较表达式得到了一些类型
e
c=d=[e]

reverse :: c -> d  -- for some c and d
reverse :: [e] -> [e] -- for some e
因此,最后两种中间体具有不同的类型

map reverse :: [[e]] -> [[e]]
reverse :: [f] -> [f]
现在我们开始尝试匹配类型。首先我要强调的是,这些显然不是真正的类型!(很抱歉所有的帽子,但我不想让任何人错过。)

下一篇作文:

map reverse . inits . reverse :: [a] -*- [[a]] = [[e]] -*> [[e]]
-- again, we have [[a]] = [[e]], so e = a, and we have
map reverse . inits . reverse :: [a] -> [[a]]
最后,我们有

reverse . map reverse . inits . reverse :: [a] -*- [[a]] = [f] -*> [f]
-- This time we have [[a]] = [f], so we must have f = [a], so the type
-- of the final composition is
tails = reverse . map reverse . inits . reverse :: [a] -> [[a]]

由于
tails
的类型为
[a]->[[a]]
,因此它必须是一个函数,接受
a
s列表作为参数,并返回
a
s列表。

这称为无点样式(其中“点”是一个数学术语,在这里基本上表示“参数”)

即使是
tails xs=…
也只是
tails=\xs->…
的语法糖,所以你需要做的就是让自己相信
tails
是一个函数

  • reverse
    map reverse
    inits
    都是功能:

    • map
      是一个高阶函数;它将一个函数作为参数,并返回另一个函数

    • reverse :: [a] -> [a]
      inits :: [b] -> [[b]]
      map :: (c -> d) -> [c] -> [d]
      
    • map reverse
      是一个函数,因为
      map
      应用于函数
      reverse

  • 两个函数的组合是另一个函数(假设类型匹配,以便我们可以关注每个组合的结果,而不是验证每个组合类型是否检查)
  • 因此

    • 相反。地图反转
      是一项功能
    • 所以<代码>相反。地图倒过来。inits是一个函数
    • 相反。地图倒过来。初始化。反转
      是一项功能

    因为
    tails
    被分配了
    reverse的值。地图倒过来。初始化。反向
    尾部
    本身也是一个函数。

    这称为无点样式(其中“点”是一个数学术语,这里基本上表示“参数”)

    reverse :: [a] -> [a]
    inits :: [b] -> [[b]]
    map :: (c -> d) -> [c] -> [d]
    
    即使是
    tails xs=…
    也只是
    tails=\xs->…
    的语法糖,所以你需要做的就是让自己相信
    tails
    是一个函数

  • reverse
    map reverse
    inits
    都是功能:

    • map
      是一个高阶函数;它将一个函数作为参数,并返回另一个函数

    • reverse :: [a] -> [a]
      inits :: [b] -> [[b]]
      map :: (c -> d) -> [c] -> [d]
      
    • map reverse
      是一个函数,因为
      map
      应用于函数
      reverse

  • 两个函数的组合是另一个函数(假设类型匹配,以便我们可以关注每个组合的结果,而不是验证每个组合类型是否检查)
  • 因此

    • 相反。地图反转
      是一项功能
    • 所以<代码>相反。地图倒过来。inits是一个函数
    • 相反。地图倒过来。初始化。反转
      是一项功能

    因为
    tails
    被分配了
    reverse的值。地图倒过来。初始化。反向
    尾部
    本身也是一种功能。

    我开始有点理解了。我试图确定为什么尾部会导致[a]->[a]]。从reverse开始(在末尾,因为),它需要[a]->[a],然后inits需要[a]->[a]],这是有效的,因为reverse的输出是[a]。在那之后,我被卡住了,因为map需要一个函数(再次反转),但也需要[a]w
    reverse :: [a] -> [a]
    inits :: [b] -> [[b]]
    map :: (c -> d) -> [c] -> [d]