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_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
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
所以你想得到
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)
签名中只有一个参数是等式中的两个参数,这看起来有点奇怪,但一旦你习惯了,你就会在野外看到这种情况。
希望这可以帮助!