实例声明中的副作用

问题描述 投票:0回答:3

说我想为UTCTime创建一个包装器:

data CustomDateStamp = CustomDateStamp
    { 
      stampValue :: UTCTime
    } deriving (Show, Eq, Ord, Typeable)

现在说我想构建一个“现在”的默认值,例如

instance Default CustomDateStamp where
    def = CustomDateStamp getCurrentTime def

这(显然)失败了:

   • Couldn't match expected type ‘UTCTime’
                  with actual type ‘IO UTCTime’
    • In the first argument of ‘CustomDateStamp’, namely ‘getCurrentTime’
      In the expression: CustomDateStamp getCurrentTime def
      In an equation for ‘def’: def = CustomDateStamp getCurrentTime def
    |
98  |     def = CustomDateStamp getCurrentTime def
    |                   ^^^^^^^^^^^^^^

我的问题是,如何在实例定义中使用sideeffecty操作?这甚至可能吗?这种情况的首选方法是什么?

haskell types default monads side-effects
3个回答
4
投票

第一个近似值:你不能这样做。一旦进入IO,总是在IO中(并且已经存在DefaultIO a实例,它不能满足您的需求)。制定不同的计划。


2
投票

我会抛出你可以为默认值需要IO动作的类型编写的混合,

instance {-# OVERLAPPING #-} Default (IO CustomDateStamp) where
    def = CustomDateStamp <$> getCurrentTime

(容易调整,例如mtl-stack)。有点争议,因为重叠是顽皮的。

编辑:需要OVERLAPPINGIO CustomDateStampIO a更具体,所以它应该在范围内选择此实例。


0
投票

因为getCurrentTime :: IO UTCTime你不能只是称之为。没有类型IO a -> a的功能

除了unsafePerformIO(和其他类似的魔法东西)。我强烈反对你不采取这条路线。


推荐问答