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

che*_*ire 7 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 
Run Code Online (Sandbox Code Playgroud)

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

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' [] [] = []
Run Code Online (Sandbox Code Playgroud)

这就是我在这里所做的.传递一个列表[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)]
Run Code Online (Sandbox Code Playgroud)

这是执行oposite的功能:

graph_to_list :: Graph -> List
graph_to_list (x:xs) = [snd (x)] ++ graph_to_list(xs)
graph_to_list []= [] 
Run Code Online (Sandbox Code Playgroud)

通过图表的地方 [(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]
Run Code Online (Sandbox Code Playgroud)

题:

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

type Function = (Nat0 -> Z) 

function_to_list :: Function -> List
Run Code Online (Sandbox Code Playgroud)

要么

list_to_function :: List -> Function
Run Code Online (Sandbox Code Playgroud)

或图表相同

function_to_graph :: Function -> Graph
graph_to_function :: Graph -> Function
Run Code Online (Sandbox Code Playgroud)

我已经在这个链接上阅读了高阶函数,但我似乎无法理解它是如何工作的.

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

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

如果有人可以在我的一些例子中向我解释更高阶的函数,我真的很感激!

编辑:

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

(list_to_graph . graph_to_list) = ? x. x
(graph_to_list . list_to_graph) = ? x. x
Run Code Online (Sandbox Code Playgroud)

如上所示,如果我将列表传递给list_to_graph它,则返回一个图表并graph_to_list执行相反的操作

(list_to_function . function_to_list) = ? x. x
(function_to_list . list_to_function) = ? x. x
Run Code Online (Sandbox Code Playgroud)

它和我想要用的其他两个函数一样.如果我申请function_to_listlist_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
Run Code Online (Sandbox Code Playgroud)

正如下面的答案所暗示的那样.

*Main> function_to_list function 
[5,2,-4,1,9,8,9]
Run Code Online (Sandbox Code Playgroud)

我想做的就是function :: Function在我的身上做到这一点list_to_function

luq*_*qui 2

所以你想得到

list_to_function :: List -> Function
Run Code Online (Sandbox Code Playgroud)

正确的?我们Graph换做吧,这样会更接近本质。我们开始写吧。

graph_to_function gph = _ -- something of type Function
Run Code Online (Sandbox Code Playgroud)

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

graph_to_function gph = \n -> _ -- something of type Z
Run Code Online (Sandbox Code Playgroud)

太好了,现在我们有一个Graph被叫gph和一个Nat0被叫n,我们想要创建一个Z. 在这里我们可以直接搜索列表n。有几种方法可以做到这一点,其中之一是:

graph_to_function gph = \n -> head ([ y | (x,y) <- gph, x == n ] ++ [0])
Run Code Online (Sandbox Code Playgroud)

我放在++ [0]最后是为了防止列表理解最终为空,也就是说,我们n在图的域中没有找到。完毕!

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

f x y z = ...
f = \x -> \y -> \z -> ...
Run Code Online (Sandbox Code Playgroud)

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

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

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

希望这可以帮助!