说我想为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
| ^^^^^^^^^^^^^^
我的问题是,如何在实例定义中使用副作用操作?这有可能吗?这种情况下首选的方法是什么?
答案 0 :(得分:4)
首先,您不能这样做。一旦进入IO,就始终处于IO中(并且Default
已经有一个IO a
实例无法执行您想要的操作)。制定不同的计划。
答案 1 :(得分:2)
我想把这种情况写成默认值需要IO操作的类型
instance {-# OVERLAPPING #-} Default (IO CustomDateStamp) where
def = CustomDateStamp <$> getCurrentTime
(可轻松调整,例如用于mtl-stack)。有点争议,因为重叠是顽皮的。
编辑:需要OVERLAPPING
,IO CustomDateStamp
比IO a
更具体,因此在范围内应选择此实例。
答案 2 :(得分:0)
自getCurrentTime :: IO UTCTime
起,您不能仅仅称呼它。没有类型为IO a -> a
除了unsafePerformIO
(以及其他类似的魔术东西)。我强烈劝阻你不要走那条路。