我有一个函数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]
答案 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
在签名中只有一个参数是方程式中的两个参数,这看起来有点奇怪,但是一旦习惯了,就可以在野外看到它。
希望这会有所帮助!