GHC版本的差异 - 编译错误

时间:2015-10-09 22:15:48

标签: haskell ghc fibonacci

我正在练习我的Haskell,我遇到了一个奇怪的问题,我无法在互联网上找到解决方案。我决定解决这个问题:

https://www.hackerrank.com/challenges/fibonacci-fp

在很多方面我都能想到。一种方法是使用memoization执行递归,其中我想使用State monad作为缓存。我的Windows 10上有GHC 7.10.2,Ubuntu 14.04上有GHC 7.6.2。下面的代码在7.6.2上编译(并且运行得非常好),并且不会在7.10.2上编译,只要我键入地图' Map'就会给出错误,例如:

  

不在范围内:类型构造函数或类:' Map.Map'

     

不在范围内:' Map.lookup'

module Main (
    main
) where

import qualified Data.Map as Map
import Control.Monad.State

type CacheState = Map.Map Int Int
type IOState a = StateT CacheState IO a

modNum :: Int
modNum = 100000007

fibsMod :: [Int]
fibsMod = 0 : 1 : zipWith (\x y -> (x + y) mod modNum ) fibsMod (tail fibsMod)

-- | calculate Fibs with memoization in map
memoizedFib :: Int -> IOState Int
memoizedFib n = do
    state <- get
    let x = Map.lookup n state
    case x of
        Just y ->
            return y
        Nothing -> do
            n1 <- memoizedFib (n - 1)
            n2 <- memoizedFib (n - 2)
            let n3 = mod (n1 + n2) modNum
            put (Map.insert n n3 state)
            return n3


query :: [Int] -> IOState ()
query [] = return ()
query (n:ns) = do
    fibNum <- memoizedFib n
    liftIO $ print fibNum
    query ns


main :: IO ()
main = do
    inputdata <- getContents
    let intList = (map (read :: String -> Int) . tail . words) inputdata

    evalIOState $ query intList
    where
        initState :: Int -> Map.Map Int Int
        initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
        --initState upTo = Map.fromList $ [(0, 0), (1, 1)]

        evalIOState :: IOState a -> IO a
        evalIOState m = evalStateT m (initState 10001)

有人知道为什么我会遇到这个问题吗?这非常令人不安。

其他问题 正如您所看到的,我没有使用memoization执行完全递归。但是,如果将这些行中的一行取消注释,可以改变方法:

initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
--initState upTo = Map.fromList $ [(0, 0), (1, 1)]

问题是使用第二行表现糟糕。我不知道我犯了什么错误,但我认为它应该在线性时间内进行记忆。然而,对于这条线,我的算法显然是指数级的(我甚至无法获得第50个Fib数的答案 - 那么长)。在这种情况下我做错了什么?

更新 感谢您的评论,我修复了我的代码。显然mod函数存在问题(我完全不知道这是如何在GHC 7.6.2上编译的)。我也改变了:

import qualified Data.Map as Map

为:

import qualified Data.Map.Strict as Map

现在这个代码按预期工作:

module Main (
    main
) where

import qualified Data.Map.Strict as Map
import Control.Monad.State

type CacheState = Map.Map Int Int
type IOState a = StateT CacheState IO a

modNum :: Int
modNum = 100000007

fibsMod :: [Int]
fibsMod = 0 : 1 : zipWith (\x y -> (x + y) `mod` modNum) fibsMod (tail fibsMod)

-- | calculate Fibs with memoization in map
memoizedFib :: Int -> IOState Int
memoizedFib n = do
    state <- get
    let x = Map.lookup n state
    case x of
        Just y ->
            return y
        Nothing -> do
            n1 <- memoizedFib (n - 1)
            n2 <- memoizedFib (n - 2)
            state <- get
            let n3 = mod (n1 + n2) modNum
            put (Map.insert n n3 state)
            return n3


query :: [Int] -> IOState ()
query [] = return ()
query (n:ns) = do
    fibNum <- memoizedFib n
    liftIO $ print fibNum
    query ns


main :: IO ()
main = do
    inputdata <- getContents
    let intList = (map (read :: String -> Int) . tail . words) inputdata

    evalIOState $ query intList
    where
        initState :: Int -> Map.Map Int Int
        --initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
        initState upTo = Map.fromList [(0, 0), (1, 1)]

        evalIOState :: IOState a -> IO a
        evalIOState m = evalStateT m (initState 10001)

所以现在问题归结为:为什么我需要使用Data.Map.Strict,它有何不同以及GHC 7.6.2为什么不需要它?

0 个答案:

没有答案