Haskell递归函数和语法

时间:2017-10-12 23:14:09

标签: list haskell recursion

我对haskell很新,并且负责创建一个带有int和一个int列表的函数,该函数会找到输入的int位置并返回它之前的值,ex fn 5 [1,2, 3,4,5,6]将返回4.我开始时遇到很多问题。首先,我一直得到变量不在范围错误。

fn' ::Int->[Int]->Int
fn' y [] = -1
fn' y (x:xs)
    |y = (head listail) = x 
    |otherwise = listail
    where listail = fn' y (tail)xs

我应该从哪里开始看,一般来说还有其他我应该或不应该做的事情?

Adams代码错误

main.hs:3:31: error:

• Couldn't match expected type ‘Int’ with actual type ‘[Int]’
• In the expression: fn y x2 : xs
  In an equation for ‘fn’:
      fn y (x1 : x2 : xs)
        | y == x2 = x1
        | otherwise = fn y x2 : xs
main.hs:3:36: error:
• Couldn't match expected type ‘[Int]’ with actual type ‘Int’
• In the second argument of ‘fn’, namely ‘x2’
  In the first argument of ‘(:)’, namely ‘fn y x2’
  In the expression: fn y x2 : xs
<interactive>:3:1: error:
• Variable not in scope: main
• Perhaps you meant ‘min’ (imported from Prelude)

1 个答案:

答案 0 :(得分:3)

您可以使用模式匹配从列表中获取两个值并进行比较。

fn :: Int -> [Int] -> Int
fn y (x1:x2:xs) | y == x2 = x1
                | otherwise = fn y (x2:xs)
fn _ _ = -1

请注意我的最后一种情况 - 当您无法匹配模式(x1:x2:xs)时,这是失败的情况。

或者:(x1:x2:xs)也可以拼写为(x1:xs@(x2:_))。后一种模式阅读起来比较复杂,但可以这样做:

fn :: Int -> [Int] -> Int
fn y (x1:xs@(x2:_)) | y == x2 = x1
                    | otherwise = fn y xs
fn _ _ = -1

而不是重新加入x2xs来递减。

Try it online!

正如加莱在评论中指出的那样:

请注意,此函数可以采用更多态的Eq a => a -> [a] -> a形式。这只是对类型签名的更改

fn :: Eq a => a -> [a] -> a

这使您可以将fn与其他有用的类型一起使用,即fn '#' "I'm #1!"给出'1'

此处更好的返回值可能是Maybe Int(或多态形式的Maybe a),因为您将拥有一些不包含搜索字词的列表。

fn :: Eq a => a -> [a] -> Maybe a
fn y (x1:xs@(x2:_)) | y == x2 = Just x1
                    | otherwise = fn y xs
fn _ _ = Nothing