如果想要可变状态,你可以不断地传递更新后的图,或者将其保存在状态单元中。 import qualified Data.Map as Map
import Control.Monad.ST
import Data.STRef
memoize :: Ord k => (k -> ST s a) -> ST s (k -> ST s a)
memoize f = do
mc <- newSTRef Map.empty
return $ \k -> do
c <- readSTRef mc
case Map.lookup k c of
Just a -> return a
Nothing -> do a <- f k
writeSTRef mc (Map.insert k a c) >> return a 可以这样用 import Control.Monad
main :: IO ()
main = do
fib <- stToIO $ fixST $ \fib -> memoize $ \n ->
if n < 2 then return n else liftM2 (+) (fib (n-1)) (fib (n-2))
mapM_ (print <=< stToIO . fib) [1..10000] 可以不安全从线程状态的需求中逃过所有需要它的东西。 import System.IO.Unsafe
unsafeMemoize :: Ord k => (k -> a) -> k -> a
unsafeMemoize f = unsafePerformIO $ do
f' <- stToIO $ memoize $ return . f
return $ unsafePerformIO . stToIO . f'
fib :: Integer -> Integer
fib = unsafeMemoize $ \n -> if n < 2 then n else fib (n-1) + fib (n-2)
main :: IO ()
main = mapM_ (print . fib) [1..1000]... 展开详请
导出Functor实例总是做显而易见的事情。这通常是很好的,但偶尔会错过机会。例如,假设我写 data Pair a = Pair a a deriving Functor
data Digit a = One a | Two a a deriving Functor
data Queue a =
Empty
| Single a
| Deep !(Digit a) (Queue (Pair a)) !(Digit a) deriving Functor 这将生成(在ghc 8.2中) instance Functor Queue where
fmap ...
x <$ Empty = Empty
x <$ Single y = Single x
x <$ Deep pr m sf = Deep (x <$ pr) (fmap (x <$) m) (x <$ sf) 用手写最后一个例子是可能的: x <$ Deep pr m sf = Deep (x <$ pr) (Pair x x <$ m) (x <$ sf) 可以看到实际的派生代码-ddump-deriv...... 展开详请