【问题标题】:Passing a function as a parameter and returning a function - Haskell将函数作为参数传递并返回函数 - Haskell
【发布时间】:2018-12-01 18:12:02
【问题描述】:

我有一个函数 f(n) 的图表,它在哪里返回

5  if n = 0 
2  if n = 1 
-4 if n = 2 
1  if n = 3 
9  if n = 4 
8  if n = 5 
9  if n = 6 
0  otherwise 

我想写一个函数来表示一个带有一对列表的图表:

type Nat0 = Int 
type Z = Int
type List = [Z] 
type Graph = [(Nat0,Z)] 

list_to_graph :: List -> Graph
list_to_graph x = list_to_graph' ([0..(length x)-1 ]) (x)

list_to_graph' :: [Int] -> List -> Graph
list_to_graph' (x:xs) (y:ys) = [(x, y)] ++ list_to_graph' (xs) (ys)
list_to_graph' [] [] = []

这就是我在这里所做的。传递列表 [5,2,-4,1,9,8,9] 返回

*Main> list_to_graph [5,2,-4,1,9,8,9]
[(0,5),(1,2),(2,-4),(3,1),(4,9),(5,8),(6,9)]

这是相反的功能:

graph_to_list :: Graph -> List
graph_to_list (x:xs) = [snd (x)] ++ graph_to_list(xs)
graph_to_list []= [] 

在哪里传递图表[(0,5),(1,2),(2,-4),(3,1),(4,9),(5,8),(6,9)]

*Main> graph_to_list [(0,5),(1,2),(2,-4),(3,1),(4,9),(5,8),(6,9)]
[5,2,-4,1,9,8,9]

问题:

我不明白的是如何写这样的东西:

type Function = (Nat0 -> Z) 

function_to_list :: Function -> List

list_to_function :: List -> Function

图形也一样

function_to_graph :: Function -> Graph
graph_to_function :: Graph -> Function

我已阅读此链接上的Higher order functions,但我似乎无法理解其实际工作原理。

我想在function_to_list 中,我必须传递一个具有此符号(Nat0 -> Z)(实际上是Int -> Int)的函数,它应该返回一个List[Z](即[Int]) .但是我该怎么做呢?这就像将相同的功能传递给自己?

更令人困惑的是list_to_function 这里的结果应该是什么?

如果有人可以在我的一些示例中向我解释高阶函数,我将不胜感激!

编辑:

在这里更清楚的是我想要实现的目标:

(list_to_graph . graph_to_list) = λ x. x
(graph_to_list . list_to_graph) = λ x. x

如上所示,如果我将列表传递给 list_to_graph,它会返回一个图表,而 graph_to_list 则相反

(list_to_function . function_to_list) = λ x. x
(function_to_list . list_to_function) = λ x. x

这与我想对其他两个函数执行的操作相同。如果我将function_to_list 应用于list_to_function,因为function_to_list 返回一个List 并且list_to_function 接受一个List,它应该返回一个函数,该函数将从列表中取出一个元素并将其应用于Function将返回Z

我现在想到了什么:

function_to_list :: Function-> List
function_to_list f = [f(x) | x <- [0..6]]

function :: Function
function n
         | n == 0 = 5
         | n == 1 = 2 
         | n == 2 = (-4)
         | n == 3 = 1
         | n == 4 = 9
         | n == 5 = 8
         | n == 6 = 9
         | otherwise = 0

正如下面的答案所建议的那样。

*Main> function_to_list function 
[5,2,-4,1,9,8,9]

我想做的是在我的list_to_function 中制作这个function :: Function

【问题讨论】:

  • 您只是在寻找function反函数。但这是不可能的,因为function 4 = function 6 = 9,不是一对一或单射函数。

标签: haskell higher-order-functions


【解决方案1】:
list_to_graph' :: [Int] -> List -> Graph
list_to_graph' (x:xs) (y:ys) = [(x, y)] ++ list_to_graph' (xs) (ys)
list_to_graph' [] [] = []

这个函数存在并且被称为zip

注意:zip 也适用于不同长度的列表,忽略较长列表的额外位,而如果两者的长度不同,你的会失败

graph_to_list :: Graph -> List
graph_to_list (x:xs) = [snd (x)] ++ graph_to_list(xs)
graph_to_list []= []

你可以把这个函数写成,

graph_to_list = map snd

graph_to_list xs = [snd x | x <- xs]

graph_to_list xs = [a | (a,b) <- xs]

关于这个,

我不明白的是如何写这样的东西:

type Function = (Nat0 -> Z) 

function_to_list :: Function -> List

如果我对您的理解正确,您希望能够构建“f 的图像”,即f 域中所有x 的所有值f x 的列表。理论上可能看起来像的东西,

[f(x) | x <- DOMAIN f]

然而,一般来说,没有办法知道给定函数的域(更不用说遍历它的方法了)。将函数转换为图形也是如此。要实现这样的“转换”,您必须提供函数 f :: A -&gt; B 和列表 xs :: A 以及您要考虑的域点作为参数。

【讨论】:

  • 感谢您的回答,我编辑了问题以更好地解释我的实际意思
  • 我明白你想要什么,但在你的编辑中function_to_list 假定点列表[0..6]。当然,这适用于特定的function,但不适用于其他人。同样要恢复并获得原始的function,您需要假设您知道所有其他点都返回0。应该是list_to_function xs = \n -&gt; if (n &gt;=0) &amp;&amp; (n&lt;=6) then xs!!n else 0
  • 请注意,snd x : graph_to_list xs 优于 [snd x] ++ graph_to_list x,因为它不会在将其合并到递归结果之前创建不必要的单例列表。
【解决方案2】:

所以你想得到

list_to_function :: List -> Function

正确吗?让我们改用Graph,它会更接近本质。让我们开始写吧。

graph_to_function gph = _ -- something of type Function

所以我们要构造Function 类型的东西,即Nat0 -&gt; Z。最无聊的方法是使用 lambda:

graph_to_function gph = \n -> _ -- something of type Z

太好了,现在我们有一个名为gphGraph 和一个名为nNat0,我们要创建一个Z。在这里,我们可以在列表中搜索n。有几种方法可以做到这一点,这里有一个:

graph_to_function gph = \n -> head ([ y | (x,y) <- gph, x == n ] ++ [0])

我把++ [0]放在最后,以防列表推导结果为空,也就是说,我们没有在图形的域中找到n。完成!

有趣的是,Haskell 中的函数默认是柯里化的,所以

f x y z = ...
f = \x -> \y -> \z -> ...

是等价的。也就是说,graph_to_function 与双参数函数实际上是一样的。所以我们可以将n 移到定义的左侧:

graph_to_function :: Graph -> Function
graph_to_function gph n = head ([ y | (x,y) <- gph, x == n ] ++ [0])

签名中只有一个参数是等式中的两个参数,这看起来有点奇怪,但是一旦你习惯了它,你就会在野外看到它。

希望这会有所帮助!

【讨论】:

  • 谢谢你,我现在很清楚。我不清楚的是如何编写 function_to_list 或 function_to_graph 作为上面提到的答案,如果不添加参数我们就无法做到。
  • @cheshire,function_to_list f = map f [0..] 做你想做的事吗?
  • 有点晚了,但 [0..] 确实有效!谢谢
猜你喜欢
  • 2021-04-13
  • 1970-01-01
  • 2018-04-09
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
相关资源
最近更新 更多