试图在haskell中实现二进制搜索

时间:2015-05-24 18:54:45

标签: haskell

我正在尝试学习haskell并在haskell中实现一些基本算法。我收到的这类消息我并不完全理解。 对于下面的代码,该函数接受一个值和一个列表,并返回列表中匹配值的索引:

#!/usr/bin/env runghc
import Data.Maybe (isNothing, fromJust)

binarySearch :: (Ord a) => a -> [a] -> Maybe Int
binarySearch x [] = Nothing
binarySearch x [y] 
  | x == y = Just 0
  | otherwise = Nothing
binarySearch x ys
  | x < centerValue = binarySearch x (fst splitted)
  | x >= centerValue = let recurse = binarySearch x (snd splitted) 
                         in if (isNothing recurse) then Nothing else (Just (centerValue + (fromJust recurse)))
    where split :: (Ord a) => [a] -> ([a], [a])
          split [] = ([],[])
          split [x] = ([x], [])
          split x = ((take halfIndex x), (take rhalfIndex (reverse x)))
            where myLength = length x
                  halfIndex = myLength `div` 2
                  rhalfIndex = myLength - halfIndex
          splitted = split ys
          centerValue = head (snd splitted)

main :: IO()
main = print(binarySearch 5 [1,2,3,4,5])

我收到错误消息:

binarySearch.hs:12:77:
    Couldn't match expected type ‘Int’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
          the type signature for
            binarySearch :: Ord a => a -> [a] -> Maybe Int
          at binarySearch.hs:4:17
    Relevant bindings include
      centerValue :: a (bound at binarySearch.hs:21:11)
      splitted :: ([a], [a]) (bound at binarySearch.hs:20:11)
      ys :: [a] (bound at binarySearch.hs:9:16)
      x :: a (bound at binarySearch.hs:9:14)
      binarySearch :: a -> [a] -> Maybe Int
        (bound at binarySearch.hs:5:1)
    In the first argument of ‘(+)’, namely ‘centerValue’
    In the first argument of ‘Just’, namely
      ‘(centerValue + (fromJust recurse))’

不确定发生了什么。有谁知道我应该做的更正以及为什么?

编辑,修正后的代码如下:

#!/usr/bin/env runghc
import Data.Maybe (isNothing, fromJust)

split :: (Ord a) => [a] -> ([a], [a])
split [] = ([],[])
split [x] = ([x], [])
split x = ((take halfIndex x), (drop halfIndex x))
  where myLength = length x
        halfIndex = myLength `div` 2

binarySearch :: (Ord a) => a -> [a] -> Maybe Int
binarySearch x [] = Nothing
binarySearch x [y] 
  | x == y = Just 1
  | otherwise = Nothing
binarySearch x ys
  | x < centerValue = binarySearch x (fst splitted)
  | x >= centerValue = let recurse = binarySearch x (snd splitted) 
                         in if (isNothing recurse) 
                            then Nothing 
                            else (Just (centerValueIndex + (fromJust recurse)))
    where splitted = split ys
          centerValue = head (snd splitted)
          centerValueIndex = (length ys) `div` 2

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

1 个答案:

答案 0 :(得分:3)

根据我对二进制搜索实现的理解,您希望获得列表中特定元素的索引。因为binarySearch的类型签名返回Maybe Int,我假设Int应该是索引。 如果是这种情况,我相信代码行:

in if (isNothing recurse) then Nothing else (Just (centerValue + (fromJust recurse)))

您正在尝试计算正确的索引。但您使用的是centerValue内容,类型为a,而不是索引,其类型应为{{1} }。除了Int之外,您可能还需要定义centerValueIndex。这应该可以解决编译错误。

但是,我也注意到你的实现中存在另一个问题,我不想破坏自己找到它的乐趣,但正如一个提示,问题出在centerValue实现中。

我自己只知道很少Haskell,但希望这可以帮助。