Functional programming 如何阅读此功能代码

Functional programming 如何阅读此功能代码,functional-programming,miranda,Functional Programming,Miranda,无法阅读(解释)此功能性Miranda代码 g = (foldr (+) 0) . (foldr ((:) . ((#) . (:[]))) []) 我知道它的作用 通过# 创建一个包含上述原始输入列表长度的单元素列表 使用foldr将新列表折叠为单个整数,并对每个元素执行操作+0 然而,我被括号弄糊涂了,看不出输入列表在哪里。最右边的[]构造函数做什么 还有,为什么这段代码只能通过函数g工作,但如果我直接调用它,它会抛出一个错误?简而言之,g是一个返回列表长度的函数 让我们把函数分成几个

无法阅读(解释)此功能性Miranda代码

g = (foldr (+) 0) . (foldr ((:) . ((#) . (:[]))) [])
我知道它的作用

  • 通过
    #
  • 创建一个包含上述原始输入列表长度的单元素列表
  • 使用
    foldr
    将新列表折叠为单个整数,并对每个元素执行操作
    +0
然而,我被括号弄糊涂了,看不出输入列表在哪里。最右边的
[]
构造函数做什么


还有,为什么这段代码只能通过函数g工作,但如果我直接调用它,它会抛出一个错误?

简而言之,
g
是一个返回列表长度的函数

让我们把函数分成几个部分

|| returns 1 for any input.
||   return_one "hoobar" = 1
return_one :: * -> num
return_one = (#) . (:[]) 

|| ignore first argument, insert 1 to the second argument.
||   insert_one "hoobar" [4,5,6] = [1,4,5,6]
insert_one :: *->[num]->[num]
insert_one = (:) . return_one

|| sum of list.
||   sum_list [7,8,9] = 24
sum_list :: [num] -> num 
sum_list = foldr (+) 0

|| generate list of 1 which as the same length of original list. 
||   change_one ["apple","banana"] = [1,1]
change_one :: [*] -> [num]
change_one = foldr insert_one []

|| return the length of the list.
||   g ["apple","banana"] = 2
g :: [*] -> num
g = sum_list . change_one
我会解释一些令人困惑的函数

返回一个
(:[])
是一个创建单个元素列表的函数,
(#)
返回长度。 严格地说,
(:[])
(:)
,它将
[]
作为第一个参数

因此,
(:[])“hoobar”=“hoobar”:[]=[“hoobar”]
,对其应用
(#)
,返回1

换一个 它以空列表开始,在列表的前面插入1

foldr insert_one [] ["apple","banana"]
= foldr insert_one [1] ["apple"]
= foldr insert_one [1,1] []

简而言之,
g
是一个返回列表长度的函数

让我们把函数分成几个部分

|| returns 1 for any input.
||   return_one "hoobar" = 1
return_one :: * -> num
return_one = (#) . (:[]) 

|| ignore first argument, insert 1 to the second argument.
||   insert_one "hoobar" [4,5,6] = [1,4,5,6]
insert_one :: *->[num]->[num]
insert_one = (:) . return_one

|| sum of list.
||   sum_list [7,8,9] = 24
sum_list :: [num] -> num 
sum_list = foldr (+) 0

|| generate list of 1 which as the same length of original list. 
||   change_one ["apple","banana"] = [1,1]
change_one :: [*] -> [num]
change_one = foldr insert_one []

|| return the length of the list.
||   g ["apple","banana"] = 2
g :: [*] -> num
g = sum_list . change_one
我会解释一些令人困惑的函数

返回一个
(:[])
是一个创建单个元素列表的函数,
(#)
返回长度。 严格地说,
(:[])
(:)
,它将
[]
作为第一个参数

因此,
(:[])“hoobar”=“hoobar”:[]=[“hoobar”]
,对其应用
(#)
,返回1

换一个 它以空列表开始,在列表的前面插入1

foldr insert_one [] ["apple","banana"]
= foldr insert_one [1] ["apple"]
= foldr insert_one [1,1] []

我不太了解Miranda,但基于Haskell(我相信两者之间的区别很小,只有
是列表长度的一元运算符,是唯一的半有效运算符,
是注释语法):
是函数组合:

(p . q) x = p (q x)
  || also can be written as:
p . q = \x -> p (q x)
函数合成是一种关联操作,因此
p。(q.r)
=
(p.q)。r
=
p。Qr

使用此信息,我们可以使用
的定义对此进行扩展:

g      = (foldr (+) 0) . (foldr ((:) . ((#) . (:[]))) [])       || Original definition
g list = foldr (+) 0 (foldr ((:) . ((#) . (:[]))) [] list)
g list = foldr (+) 0 (foldr (\x -> (:) (((#) . (:[])) x)) [] list)
g list = foldr (+) 0 (foldr (\x -> (:) ((\y -> (#) ((:[]) y)) x)) [] list)
这可以进一步清理:

g list = foldr (+) 0 (foldr (\x -> (:) ((\y -> (#)(y:[])) x)) [] list) || More conventional operator syntax for the innermost `:`
g list = foldr (+) 0 (foldr (\x -> (:) ((#)(x:[]))) [] list)           || Innermost lambda was applied to x. Substitute y for x.
g list = foldr (+) 0 (foldr (\x -> (:) ((#)([x]))) [] list)            || Apply innermost `:`
g list = foldr (+) 0 (foldr (\x -> (:) #[x])) [] list)                 || Remove unnecessary parentheses
g list = foldr (+) 0 (foldr (\x acc -> (:) (#[x]) acc) [] list)        || Explicitly write implicit argument. This particular step is called eta-expansion
g list = foldr (+) 0 (foldr (\x acc -> (:) 1 acc) [] list)             || #[x] is always 1, no matter what x is
g list = foldr (+) 0 (foldr (\x acc -> 1 : acc) [] list)               || More conventional syntax for `:`
还要注意,
foldr
并不像您在问题中所说的那样,将
+0
应用于每个元素
foldr op z(a:b:c:[])
变成
op a(op b(op c z))
a:b:c:[]
是另一种编写
[a,b,c]
的方式)。我一直认为这个图表有助于理解:


此外,直接调用时出错的原因很可能是
p。q x
(p.q)x

不同,我不太了解米兰达,但基于Haskell(我认为两者之间的区别很小,只有
#
是列表长度的一元运算符,是唯一的半有效运算符,
|
是注释语法):该
为函数组合:

(p . q) x = p (q x)
  || also can be written as:
p . q = \x -> p (q x)
函数合成是一种关联操作,因此
p。(q.r)
=
(p.q)。r
=
p。Qr

使用此信息,我们可以使用
的定义对此进行扩展:

g      = (foldr (+) 0) . (foldr ((:) . ((#) . (:[]))) [])       || Original definition
g list = foldr (+) 0 (foldr ((:) . ((#) . (:[]))) [] list)
g list = foldr (+) 0 (foldr (\x -> (:) (((#) . (:[])) x)) [] list)
g list = foldr (+) 0 (foldr (\x -> (:) ((\y -> (#) ((:[]) y)) x)) [] list)
这可以进一步清理:

g list = foldr (+) 0 (foldr (\x -> (:) ((\y -> (#)(y:[])) x)) [] list) || More conventional operator syntax for the innermost `:`
g list = foldr (+) 0 (foldr (\x -> (:) ((#)(x:[]))) [] list)           || Innermost lambda was applied to x. Substitute y for x.
g list = foldr (+) 0 (foldr (\x -> (:) ((#)([x]))) [] list)            || Apply innermost `:`
g list = foldr (+) 0 (foldr (\x -> (:) #[x])) [] list)                 || Remove unnecessary parentheses
g list = foldr (+) 0 (foldr (\x acc -> (:) (#[x]) acc) [] list)        || Explicitly write implicit argument. This particular step is called eta-expansion
g list = foldr (+) 0 (foldr (\x acc -> (:) 1 acc) [] list)             || #[x] is always 1, no matter what x is
g list = foldr (+) 0 (foldr (\x acc -> 1 : acc) [] list)               || More conventional syntax for `:`
还要注意,
foldr
并不像您在问题中所说的那样,将
+0
应用于每个元素
foldr op z(a:b:c:[])
变成
op a(op b(op c z))
a:b:c:[]
是另一种编写
[a,b,c]
的方式)。我一直认为这个图表有助于理解:


此外,直接调用时出错的原因很可能是
p。q x
(p.q)x
不同,当你说“直接调用”时,你是什么意思?在live editor中运行RHS,而不是在脚本编辑器中声明g。当你说“直接调用”时,你是什么意思?在live editor中运行RHS,而不是在脚本编辑器中声明g,以便返回\u one为什么需要
?这是附录,为什么作为空列表构造函数,
[]
不够?还有,为什么这个函数在live editor(
:[]
)中不起作用?我不知道live editor是什么意思,因为我在REPL中工作,但是你试过评估
(:[])3
?啊,我现在明白了。我没有将函数作为前缀来读取。对于return\u one,为什么需要
?这是附录,为什么作为空列表构造函数,
[]
不够?还有,为什么这个函数在live editor(
:[]
)中不起作用?我不知道live editor是什么意思,因为我在REPL中工作,但是你试过评估
(:[])3
?啊,我现在明白了。我没有将函数作为前缀读取。谢谢,在计算图形时打印/查看求值堆栈吗?@clicky我从未使用过Miranda,所以我不确定。我怀疑没有,因为(我相信)米兰达几十年来一直没有得到积极的发展。但我不熟悉米兰达工具。不过,在开发的不同阶段有一些Haskell工具(我没有使用过),比如@clicky(我在问题的最后一部分也添加了一些内容)谢谢,在计算图表时打印/查看评估堆栈吗?@clicky我从来没有使用过Miranda,所以我不确定。我怀疑没有,因为(我相信)米兰达几十年来一直没有得到积极的发展。但我不熟悉米兰达工具。尽管如此,在不同的开发阶段,仍有一些Haskell工具(w