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_Functional Programming_Currying - Fatal编程技术网

Haskell函数的应用与实现

Haskell函数的应用与实现,haskell,functional-programming,currying,Haskell,Functional Programming,Currying,我总是对学习新语言感兴趣,这一事实让我保持警觉,并使我(我相信)成为一名更好的程序员。我征服哈斯凯尔的尝试来了又去——到目前为止已经两次了——我决定是时候再试一次了。第三次是魅力,对吗 没有。我重新阅读我的旧笔记。。。并感到失望:-( 上次让我失去信心的问题很简单:整数的排列。 i、 e.从整数列表到列表列表-其排列列表: [int] -> [[int]] 这实际上是一个通用问题,因此将上面的“int”替换为“a”仍然适用 从我的笔记中: 我自己先编码,我成功了。万岁 我将我的解决方案发

我总是对学习新语言感兴趣,这一事实让我保持警觉,并使我(我相信)成为一名更好的程序员。我征服哈斯凯尔的尝试来了又去——到目前为止已经两次了——我决定是时候再试一次了。第三次是魅力,对吗

没有。我重新阅读我的旧笔记。。。并感到失望:-(

上次让我失去信心的问题很简单:整数的排列。 i、 e.从整数列表到列表列表-其排列列表:

[int] -> [[int]]
这实际上是一个通用问题,因此将上面的“int”替换为“a”仍然适用

从我的笔记中:

我自己先编码,我成功了。万岁

我将我的解决方案发送给我的一位好朋友——哈斯凯尔·古鲁(Haskell guru),这通常有助于向古鲁学习——他给我发送了这封信,我被告知,“表达了语言的真正力量,使用通用工具来编码你的需求”。为此,我最近喝了kool aid,让我们走:

permute :: [a] -> [[a]]
permute = foldr (concatMap.ins) [[]]
   where ins x []     = [[x]]
         ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
…作为…的另一种语法

f (g x) 
在古鲁发送的代码中,DOT是从foldr中使用的,“ins”函数作为fold“collapse”:

好的,因为我想了解古鲁是如何使用圆点的,所以我尝试根据圆点定义使用等价的表达式,(f.g)x=f(gx)

…我所做的是正确的,明智的:

(concatMap . ins) x y = concatMap (ins x y)
挠头

*Main> concatMap (ins 1) [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
所以…DOT的解释显然是 太简单了…多特一定很聪明,能理解 事实上,我们希望“ins”能被咖喱带走,先“吃” 参数-因此成为只想在[t]上操作的函数 (并在所有可能的位置上用“1”来“散布”它们)

但这是在哪里指定的?当我们调用时,GHC如何知道这样做:

*Main> (concatMap . ins) 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
“移民局”的签名是否以某种方式传达了“吃我的第一个论点”的政策

我看不出有什么特别的——“ins”是一个带“t”的函数, 一个“t”的列表,并继续创建一个包含所有“人际关系”的列表。与“吃掉你的第一个论点并把它咖喱掉”无关

所以…我很困惑。我理解(在看了一个小时的代码之后!)发生了什么,但是…万能的上帝…也许GHC试图看看它能“剥离”多少个论点

再一次-哎呀

由于我总是将我正在学习的语言与我已经知道的语言进行比较,“ins”在Python中会是什么样子

a=[2,3]
print [a[:x]+[1]+a[x:] for x in xrange(len(a)+1)]

[[1, 2, 3], [2, 1, 3], [2, 3, 1]]
老实说,现在…哪一个更简单

我的意思是,我知道我是Haskell的新手,但我觉得自己像个白痴…看了4行代码一个小时,最后假设编译器…尝试各种解释,直到找到“点击”的东西

引用致命武器的话,“我太老了,不能这样做”

这是真的,你由此得出结论

(f . g) x y = f (g x y)
也必须是正确的,但事实并非如此。事实上,以下是正确的:

(f . g) x y = f (g x) y
这是不一样的

为什么这是真的?那么
(f.g)xy
((f.g)x)y
是一样的,因为我们知道
(f.g)x=f(gx)
我们可以把它简化为
(f(gx))y
,这与
f(gx)y
一样

所以
(concatMap.ins)1[[2,3]]
相当于
concatMap(ins 1)[[2,3]]]
。这里没有魔法

另一种方法是通过以下类型:

具有类型
(b->c)->(a->b)->a->c
concatMap
具有类型
(x->[y])->[x]->[y]
ins
具有类型
t->[t]->[t]]
。如果我们使用
concatMap
作为
b->c
参数,
ins
作为
a->b
参数,那么
a
变成
t
b
变成
[t]-[t]
c
变成
[t]-[t]
(带有
x
y
=
[t]


因此,
concatMap.ins
的类型是
t->[[t]]->[[t]]]
,这意味着一个函数获取一个whatever和一个列表(whatever)并返回一个列表(相同类型).

我想加上我的两分钱。问答听起来像是
是一个神奇的操作符,它通过重新安排函数调用来做奇怪的事情。事实并非如此。
只是函数组合。下面是Python中的一个实现:

def dot(f, g):
    def result(arg):
        return f(g(arg))
    return result
它只是创建一个新函数,将
g
应用于参数,将
f
应用于结果,并返回应用
f
的结果

所以
(concatMap.ins)1[[2,3]]
是说:创建一个函数,
concatMap.ins
,并将其应用于参数
1
[[2,3]]]
。当您执行
concatMap(ins 1[[2,3]])
您的意思是,将函数
concatMap
应用于
ins
应用于
1
[[2,3]]
的结果,正如您从Haskell可怕的错误消息中发现的,这是完全不同的


更新:进一步强调这一点。您说过
(f.g)x
f(gx)
的另一种语法。这是错误的
只是一个函数,因为函数可以有非字母数字名称(
>您想得太多了。您可以使用简单的等式推理解决所有问题。让我们从头开始尝试:

permute = foldr (concatMap . ins) [[]]
这可以简单地转换为:

permute lst = foldr (concatMap . ins) [[]] lst
concatMap
可定义为:

concatMap f lst = concat (map f lst)
foldr
处理列表的方式是(例如):

大概是

permute [1, 2, 3]
变成:

foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 
    ((concatMap . ins) 2
       ((concatMap . ins) 3 [[]]))
让我们完成第一个表达式:

(concatMap . ins) 3 [[]]
= (\x -> concatMap (ins x)) 3 [[]]  -- definition of (.)
= (concatMap (ins 3)) [[]]
= concatMap (ins 3) [[]]     -- parens are unnecessary
= concat (map (ins 3) [[]])  -- definition of concatMap
现在,ins 3[]=[3]
,所以

map (ins 3) [[]] == (ins 3 []) : []  -- definition of map
= [3] : []
= [[3]]
所以我们最初的表达是:

foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 
    ((concatMap . ins) 2
       ((concatMap . ins) 3 [[]]))
= (concatMap . ins) 1 
    ((concatMap . ins) 2 [[3]]
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 [[2, 3], [3, 2]]
= (\x -> concatMap (ins x)) 1 [[2, 3], [3, 2]]
= concatMap (ins 1) [[2, 3], [3, 2]]
= concat (map (ins 1) [[2, 3], [3, 2]])
= concat [ins 1 [2, 3], ins 1 [3, 2]] -- definition of map
= concat [[[1, 2, 3], [2, 1, 3], [2, 3, 1]], 
          [[1, 3, 2], [3, 1, 2], [3, 2, 1]]]  -- defn of ins
= [[1, 2, 3], [2, 1, 3], [2, 3, 1], 
   [1, 3, 2], [3, 1, 2], [3, 2, 1]]
让我们努力完成

(concatMap . ins) 2 [[3]]
= (\x -> concatMap (ins x)) 2 [[3]]
= (concatMap (ins 2)) [[3]]
= concatMap (ins 2) [[3]]     -- parens are unnecessary
= concat (map (ins 2) [[3]])  -- definition of concatMap
= concat (ins 2 [3] : [])
= concat ([[2, 3], [3, 2]] : [])
= concat [[[2, 3], [3, 2]]]
= [[2, 3], [3, 2]]
所以我们最初的表达是:

foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 
    ((concatMap . ins) 2
       ((concatMap . ins) 3 [[]]))
= (concatMap . ins) 1 
    ((concatMap . ins) 2 [[3]]
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 [[2, 3], [3, 2]]
= (\x -> concatMap (ins x)) 1 [[2, 3], [3, 2]]
= concatMap (ins 1) [[2, 3], [3, 2]]
= concat (map (ins 1) [[2, 3], [3, 2]])
= concat [ins 1 [2, 3], ins 1 [3, 2]] -- definition of map
= concat [[[1, 2, 3], [2, 1, 3], [2, 3, 1]], 
          [[1, 3, 2], [3, 1, 2], [3, 2, 1]]]  -- defn of ins
= [[1, 2, 3], [2, 1, 3], [2, 3, 1], 
   [1, 3, 2], [3, 1, 2], [3, 2, 1]]
这里没有什么神奇之处。我想你可能会感到困惑,因为很容易假设
concatMap=concat
permute [1, 2, 3]
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 
    ((concatMap . ins) 2
       ((concatMap . ins) 3 [[]]))
(concatMap . ins) 3 [[]]
= (\x -> concatMap (ins x)) 3 [[]]  -- definition of (.)
= (concatMap (ins 3)) [[]]
= concatMap (ins 3) [[]]     -- parens are unnecessary
= concat (map (ins 3) [[]])  -- definition of concatMap
map (ins 3) [[]] == (ins 3 []) : []  -- definition of map
= [3] : []
= [[3]]
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 
    ((concatMap . ins) 2
       ((concatMap . ins) 3 [[]]))
= (concatMap . ins) 1 
    ((concatMap . ins) 2 [[3]]
(concatMap . ins) 2 [[3]]
= (\x -> concatMap (ins x)) 2 [[3]]
= (concatMap (ins 2)) [[3]]
= concatMap (ins 2) [[3]]     -- parens are unnecessary
= concat (map (ins 2) [[3]])  -- definition of concatMap
= concat (ins 2 [3] : [])
= concat ([[2, 3], [3, 2]] : [])
= concat [[[2, 3], [3, 2]]]
= [[2, 3], [3, 2]]
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 [[2, 3], [3, 2]]
= (\x -> concatMap (ins x)) 1 [[2, 3], [3, 2]]
= concatMap (ins 1) [[2, 3], [3, 2]]
= concat (map (ins 1) [[2, 3], [3, 2]])
= concat [ins 1 [2, 3], ins 1 [3, 2]] -- definition of map
= concat [[[1, 2, 3], [2, 1, 3], [2, 3, 1]], 
          [[1, 3, 2], [3, 1, 2], [3, 2, 1]]]  -- defn of ins
= [[1, 2, 3], [2, 1, 3], [2, 3, 1], 
   [1, 3, 2], [3, 1, 2], [3, 2, 1]]