2017-02-20 101 views
0

我写了数据类型和实例Monad类。下面是我的源代码:解决Haskell中的记忆问题

data UI a = UI { unUI :: a } 
      deriving Functor 


instance Applicative UI where 
    pure = UI 
    m *> k = m >>= \ _ -> k 
    m <* k = m >>= \ _ -> m 
    m <*> k = UI $ (unUI m) (unUI k) 


instance Monad UI where 
    m >> k = m >>= \ _ -> k 
    m >>= k = k $ unUI m 
    return = UI 

但是,当我使用功能如下图所示:

generateUUID :: UI String 
generateUUID = do 
    ruuid <- liftIO $ UV4.nextRandom 
    return $ UV.toString ruuid 

我遇到的问题与记忆化! 做一些事情是否可行?

+0

而对于MonadIO'实例MonadIO UI,其中 liftIO a =返回$ unsafePerformIO a' – QSpider

+1

您如何期待memoization来应对IO操作的状态? – jakubdaniel

+1

如果有人滥用'unsafePerformIO',将不会有什么保证:这就是为什么它是不安全的!只有当你不关心什么时候或者如果IO被触发时才能安全地使用它。为什么不直接使用'IO' monad呢?你甚至可以包装它,如果你想作为'newtype UI a = UI {unUI :: IO a}'并且围绕它定义你的实例。 – chi

回答

5

通过使用unsafePerformIO来隐藏IO行为中出现的效果,您故意(并且非常可能非法)进入纯函数领域。在那个领域,它被允许记忆/重构。编译器通常会尽量使用纯度来避免运行时的冗余工作。是否有真正的理由为什么你会隐藏这种不纯物质,特别是在可以期待与外部世界(人类)互动的东西UI中?这可能表明设计不好。您的UI似乎与Identity相同,这是最简单的仿函数,没有任何不纯效应。