如何在IO monad中包装的值上使用数据构造函数?

时间:2019-05-31 07:25:11

标签: haskell

所以我在haskell中有一个数据类型,定义如下:

import qualified Data.UUID as UUID
import qualified Data.Time.Clock as CLK

data MyRecord = MyRecord {
    id :: UUID.UUID,
    creationDate :: CLK.UTCTime,
    comment :: String
}

现在的问题是UUID和UTCTime是在IO monad中返回的。我用来生成它们的函数具有以下类型

用于UUID

nextRandom :: IO uuid-types-1.0.3:Data.UUID.Types.Internal.UUID

获取当前时间戳记:

getCurrentTime :: IO UTCTime

我的问题是如何使用数据构造函数实际初始化数据类型?

我可以执行以下操作

MyRecord <$> nextRandom

这可行,但是我不明白如何为构造函数提供其他参数。

2 个答案:

答案 0 :(得分:3)

您可以为此使用顺序应用程序 (<*>) :: Applicative f => f (a -> b) -> f a -> f b。例如:

MyRecord <$> nextRandom <*> getCurrentTime <*> return "some comment"

这等效于:

some_function :: IO MyRecord
some_function = do
    r <- nextRandom
    t <- getCurrentTime
    return (MyRecord r t "some comment")

这基本上发生的是,如果您写:

MyRecord <$> nextRandom

您构造一个IO (UTCTime -> String -> MyRecord)类型的项目。现在,通过将(<*>)函数与该函数一起用作左操作数,并将IO UTCTime作为右操作数,我们就可以构造一个IO (String -> MyRecord)类型的对象。

我们可以使用return :: Monad m => a -> m apure :: Applicative f => a -> f aString转换为IO String,因此我们再次使用(<*>)将其应用于部分数据构造函数。

答案 1 :(得分:2)

这是常见的applicative style pattern

MyRecord <$> nextRandom
         <*> getCurrentTime
         <*> pure "my comment"