在 Haskell 的 do 上下文中应用构造函数

Jiv*_*van 2 constructor haskell

鉴于以下声明

data MyCustomString = MyCustomString String deriving (Show, Eq)

getSomeString :: IO String
Run Code Online (Sandbox Code Playgroud)

我想在上下文中将 的输出处理getSomeString为 a :IO MyCustomStringdo

do
    cs_one <- getSomeString
    cs_two <- getSomeString

    -- at this point, `cs_one` and `cs_two` are of type `String`
    -- how to construct them into `MyCustomString` instead with no additional lines?
Run Code Online (Sandbox Code Playgroud)

但是,getSomeString返回 anString而不是MyCustomString。我怎样才能使用MyCustomString构造函数,使cs_onecs_two都在代码中的这一点上是类型MyCustomString

我试过这个无济于事:

-- this does not work
do
    MyCustomString cs_one <- getSomeString
    MyCustomString cs_two <- getSomeString

-- this neither
do
    cs_one <- MyCustomString getSomeString
    cs_two <- MyCustomString getSomeString
Run Code Online (Sandbox Code Playgroud)

K. *_*uhr 7

通常的方法是:

do
    cs_one <- MyCustomString <$> getSomeString
    cs_two <- MyCustomString <$> getSomeString
Run Code Online (Sandbox Code Playgroud)

<$>运营商的代名词fmap,并有签名:

(<$>) :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

由于 monad 是函子,因此它专门针对 monadIO为:

(<$>) :: (a -> b) -> IO a -> IO b
Run Code Online (Sandbox Code Playgroud)

它在 IO monad“下”应用了一个函数,在这种情况下将您IO StringIO MyCustomString.


Fyo*_*kin 5

由于getSomeString返回 an IO String,并且构造函数需要一个裸字符串,因此您不能仅将构造函数应用于getSomeString

首先,您必须实际生成该字符串,然后您可以将其包装在构造函数中:

do
    cs_one_str <- getSomeString
    let cs_one = MyCustomString cs_one_str
    ...
Run Code Online (Sandbox Code Playgroud)

或者您可以使用该fmap函数,它的作用与上面的代码片段完全相同:

    cs_one <- fmap MyCustomString getSomeString
Run Code Online (Sandbox Code Playgroud)

或者它的操作符别名<$>

    cs_one <- MyCustomString <$> getSomeString
Run Code Online (Sandbox Code Playgroud)