初学者haskell代码是完全错误的

时间:2015-05-23 03:06:03

标签: haskell

我是哈斯凯尔的新手。试图用递归实现一些非常简单的东西。返回列表中第一个匹配值的索引的函数。下面的代码不起作用,不知道为什么,有谁知道如何更正此代码?

linear_search :: (Eq a) => a -> [a] -> a
linear_search b w = linear_search_tail 0 b w
  where linear_search_tail :: (Eq a) => a -> a -> [a] -> a
        linear_search_tail x y [] = -1
        linear_search_tail x y (z:zs)
          | y == z = x
          | otherwise = linear_search_tail (x+1) y zs

main :: IO ()
main = print (linear_search 1 [2,5,4,3,7,3,1,2,3,4,5,7,8])

编辑:搞定了。这是正确的代码:

#!/usr/bin/env runghc

linear_search :: (Eq a) => a -> [a] -> Int
linear_search b w = linear_search_tail 0 b w
  where linear_search_tail :: (Eq a) => Int -> a -> [a] -> Int 
        linear_search_tail x y [] = -1
        linear_search_tail x y (z:zs)
              | y == z = x
              | otherwise = linear_search_tail (x+1) y zs

main :: IO ()
main = print (linear_search 1 [2,5,4,3,7,3,1,2,3,4,5,7,8])

2 个答案:

答案 0 :(得分:3)

代码正在搜索数字的索引,这意味着应返回Int

linear_search :: (Eq a) => a -> [a] -> Int

还有一个类似的问题,看看你能不能找到答案!

  

linear_search_tail :: (Eq a) => Int -> a -> [a] -> Int

答案 1 :(得分:3)

让我对纠正后的代码添加一些评论:

linear_search :: (Eq a) => a -> [a] -> Int
linear_search b w = linear_search_tail 0 b w
  where linear_search_tail :: (Eq a) => Int -> a -> [a] -> Int 
        linear_search_tail x y [] = -1
        linear_search_tail x y (z:zs)
              | y == z = x
              | otherwise = linear_search_tail (x+1) y zs

在辅助函数中,第二个参数y不变地传递,所以它总是等于b。您可以删除参数并直接使用:

linear_search :: (Eq a) => a -> [a] -> Int
linear_search b w = linear_search_tail 0 w
  where -- linear_search_tail :: (Eq a) => Int -> [a] -> Int 
        linear_search_tail x [] = -1
        linear_search_tail x (z:zs)
              | b == z    = x
              | otherwise = linear_search_tail (x+1) zs

(这里我必须删除/注释内部类型签名,因为Haskell将内部a类型变量解释为独立于外部a - 您可以通过启用来声明它们是相同的扩展,但让我们保持简单,只是省略签名。)

上述函数在出错时返回-1。这在Haskell中不是惯用的,其中更常见的是返回Maybe Int,这是一个包含表示整数Just 0, Just 1, Just 2, ...的值加上可以解释为“no”的不同值Nothing的类型结果”。如果我们使用它,我们得到:

linear_search :: (Eq a) => a -> [a] -> Maybe Int
linear_search b w = linear_search_tail 0 w
  where linear_search_tail x [] = Nothing
        linear_search_tail x (z:zs)
              | b == z    = Just x
              | otherwise = linear_search_tail (x+1) zs

请注意,这会使生命更少更方便调用者,现在将其索引包装在Just框中,或Nothing。这实际上是一件好事,因为现在调用者不能轻易忘记检查“未找到”的情况并使用一个普通的整数来假装它不是-1。调用者现在被迫使用类似

的东西
case linear_search 1 [2,3,4,5] of
   Just x  -> "Found at position " ++ x
   Nothing -> "Not found!"

最后,请注意第一行

linear_search b w = linear_search_tail 0 w

也可以写成

linear_search b = linear_search_tail 0

也就是说,您可以在定义的尾随位置省略相同的变量。这称为eta-reduction,并不一定会使您的代码看起来更好。在这种情况下,它没有多大帮助。我只是提到它,因为你可能会在将来看到这样的代码。

在您学习了更多Haskell之后,您可能想知道如何利用库函数。例如,来自elemIndex的{​​{1}}库函数执行您尝试编写的线性搜索。可替代地,

Data.List

你可能现在发现这个不可读,但是你可以继续学习,并在你更熟悉Haskell之后再回过头来。与此同时,像你一样编写递归函数是正确的方法。