将函数作为参数传递并返回函数-Haskell

时间:2018-12-01 18:12:02

标签: haskell higher-order-functions

我有一个函数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)的函数,并且该函数应返回一个{{ 1}}(即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]

2 个答案:

答案 0 :(得分:3)

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的所有值x {1}}。理论上可能是这样

f

但是,通常没有办法知道给定函数的域(更不用说遍历它了)。将函数转换为图形也是如此。要实现这种“转换”,您必须提供函数[f(x) | x <- DOMAIN f] 和列表f :: A -> B以及要考虑的域点作为参数。

答案 1 :(得分:2)

所以您正在尝试

list_to_function :: List -> Function

正确吗?让我们来做Graph,它将更接近本质。让我们开始编写它。

graph_to_function gph = _ -- something of type Function

因此,我们想要构造Function类型的东西,即Nat0 -> Z。最无聊的方法是使用lambda:

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

太好了,现在我们有一个名为Graph的{​​{1}}和一个名为gph的{​​{1}},我们想制作一个Nat0。在这里,我们可以在列表中搜索n。有几种方法可以做到这一点,这是一种:

Z

我将n放在最后,以防列表理解最终为空,也就是说,在图的域中没有找到graph_to_function gph = \n -> head ([ y | (x,y) <- gph, x == n ] ++ [0]) 。完成!

有趣的是,Haskell中的函数默认情况下处于咖喱状态,所以

++ [0]

是等效的。也就是说,n实际上与两个参数的函数相同。因此,我们可以将f x y z = ... f = \x -> \y -> \z -> ... 移到定义的左侧:

graph_to_function

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

希望这会有所帮助!