GHC版本的差异
我正在练习我的Haskell,遇到了一个奇怪的问题,我无法在Internet上找到解决方案。 我决定解决这个问题:
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不需要它?
链接地址: http://www.djcxy.com/p/43189.html上一篇: Difference in GHC versions
下一篇: An option to make memoization the default behaviour of Haskell