过了一段时间,我决定回去学习一些函数式编程.我这次决定选择Haskell,因为它的功能和语法.
目前我正在做一些练习而且我被困住了.我想编写一个函数,从列表中选择第二个最后一个元素,即给定[1,2,3,4]它将为3.
这是我的功能.
lastButOne xs
| null xs = xs
| length xs == 1 = xs
| length xs == 2 = lastButOne head xs
| otherwise = lastButOne tail xs
Run Code Online (Sandbox Code Playgroud)
不幸的是,它产生了一些错
Couldn't match expected type `[a]' with actual type `[a1] -> [a1]'
Relevant bindings include
xs :: [a] (bound at lastButOne.hs:1:12)
lastButOne :: [a] -> [a] (bound at lastButOne.hs:1:1)
Probable cause: `tail' is applied to too few arguments
In the first argument of `lastButOne', namely `tail'
In the expression: lastButOne tail xs
Run Code Online (Sandbox Code Playgroud)
我尝试了一些parthness,比如(head xs)和(tail xs),但它没有帮助.
Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [[a]]
Actual type: [a]
Relevant bindings include
xs :: [a] (bound at lastButOne.hs:1:12)
lastButOne :: [a] -> [a] (bound at lastButOne.hs:1:1)
In the first argument of `head', namely `xs'
In the first argument of `lastButOne', namely `(head xs)'
Run Code Online (Sandbox Code Playgroud)
后续行动:或者我应该写后续行动.好吧,我的原始想法是编写一个函数,如果列表长度为1,则生成head元素.所以考虑到Lee的解释,很容易想出以下内容:
lastPattern :: [a] -> Maybe a
lastPattern [] = Nothing
lastPattern [x] = Just x
lastPattern [x,_] = Just x
lastPattern (_:xs) = lastPattern xs
Run Code Online (Sandbox Code Playgroud)
这是第一个问题.条件[x]和[x,_]的模式是什么?
我想做的下一件事就是用反向编写相同的函数(正如Paul Johnson所指出的那样).我很快想出了head (tail (reverse [1,2,3,4]))在REPL中似乎工作得很好的东西.但是当我开始进行一些编码时,我最终得到了
lastRev :: [a] -> a
lastRev xs
| null xs = error "empty list"
| length xs == 1 = error "too short"
| otherwise = head (tail (reverse xs))
Run Code Online (Sandbox Code Playgroud)
因为头部功能是head :: [a] -> a.上面的功能对我来说有点乱,所以说.有什么方法可以让它成为现实:: [a] -> Maybe a吗?这是第二个问题.
最后但并非最不重要 - 第三个问题.哪个功能在性能方面更好?我怎样才能在Haskell中测量它?
(head xs)返回一个a,你试图将它传递到lastButOne需要[a]参数的地方.head xs在这种情况下你可以直接返回.前两个案例也有问题,因为它们返回一个列表,而元素是必需的.由于在这种情况下没有这样的元素,您可能会返回错误:
lastButOne :: [a] -> a
lastButOne xs
| null xs = error "empty list"
| length xs == 1 = error "list too short"
| length xs == 2 = head xs
| otherwise = lastButOne (tail xs)
Run Code Online (Sandbox Code Playgroud)
更功能的解决方案是在函数类型中编码偏好并返回一个,Maybe a这样Nothing如果输入列表太短,你就可以返回:
lastButOne :: [a] -> Maybe a
lastButOne xs
| null xs = Nothing
| length xs == 1 = Nothing
| length xs == 2 = Just (head xs)
| otherwise = lastButOne (tail xs)
Run Code Online (Sandbox Code Playgroud)
最后,更好的解决方案是使用模式匹配而不是保护长度:
lastButOne :: [a] -> Maybe a
lastButOne [] = Nothing
lastButOne [_] = Nothing
lastButOne [x,_] = Just x
lastButOne (_:xs) = lastButOne xs
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2686 次 |
| 最近记录: |