Binding functions that take multiple arguments

我的未来我决定 提交于 2019-11-30 08:24:15
AndrewC

TL;DR:

writeFile <$> getFilename <*> getString >>= id   :: IO ()

Monads are Applicative

Since ghc 7.10 every Monad (including IO) is also an Applicative, but even before that, you could make an Applicative out of any Monad using the equivalent of

import Control.Applicative -- not needed for ghc >= 7.10

instance Applicative M where
  pure x = return x
  mf <*> mx = do
    f <- mf
    x <- mx
    return (f x)

And of course IO is a functor, but Control.Applicative gives you <$> which can be defined as f <$> mx = fmap f mx.

Use Applicative to use functions that take as many arguments as you like

<$> and <*> let you use pure functions f over arguments produced by an Applicative/Monadic computation, so if f :: String -> String -> Bool and getFileName, getString :: IO String then

f <$> getFileName <*> getString :: IO Bool

Similarly, if g :: String -> String -> String -> Int, then

g <$> getString <*> getString <*> getString :: IO Int

From IO (IO ()) to IO ()

That means that

writeFile <$> getFilename <*> getString :: IO (IO ())

but you need something of type IO (), not IO (IO ()), so we need to either use join :: Monad m => m (m a) -> m a as in Xeo's comment, or we need a function to take the monadic result and run it, i.e. of type (IO ()) -> IO () to bind it with. That would be id then, so we can either do

join $ writeFile <$> getFilename <*> getString :: IO ()

or

writeFile <$> getFilename <*> getString >>= id :: IO ()

It's much easier to use do notation for this, rather than asking for a combinator

action1 :: MyMonad a
action2 :: MyMonad b
f :: a -> b -> MyMonad c

do
    x <- action1
    y <- action2
    f x y
Sibi

This typechecks:

import System.IO

filepath :: IO FilePath
filepath = undefined

someString :: IO String
someString = undefined

testfun = filepath   >>= (\fp -> 
          someString >>= (\str -> 
          writeFile fp str  ))

But I feel using do notation is more readable.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!