使用组合仿函数的应用实例

Using Applicative instance of composed functors

我有两个表单函数

foo :: Int -> IO String

bar :: Int -> IO Integer

基本上存在于由 (->) IntIO 组成的函子中。 现在,具有类型

的功能
baz :: String -> Integer -> Float

我想使用

等应用语法将其提升到 Int -> IO _ 上下文
foobarbaz :: Int -> IO Float
foobarbaz = baz <$> foo <*> bar

如果我这样做,编译器会用

对我大喊大叫
Couldn't match type `IO String' with `[Char]'
      Expected type: Int -> String
        Actual type: Int -> IO String

就好像它只是试图将应用程序实例用于 (->) Int

我认为应用仿函数是组合的,这样我就可以将应用实例用于组合仿函数。我错了吗?还是我应该向编译器提供更多信息?

我也尝试启用 TypeApplications 来明确指定我想使用的仿函数,但我意识到我不能写 (->) Int (IO _)。真的有办法吗?

I thought applicative functors composed, so that I could use the applicative instance for the composed functor.

这是正确的,但是假设我们采用 f ~ (->) Int,那么类型是 (<$>) :: (a -> b) -> (Int -> a) -> (Int -> b)(<*>) :: (Int -> (a -> b)) -> (Int -> a) -> (Int -> b),但这与类型不匹配,因为 [=13] =] 需要一个 String 和一个 Integer,而 foo returns 一个 IO Stringbar 一个 IO Integer.

您可以利用 liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c 提升 baz 功能以使用 IO 操作的结果:

import Control.Applicative(liftA2)

foobarbaz :: Int -> IO Float
foobarbaz = <b>liftA2</b> baz <$> foo <*> bar
因此,

liftA2 会将 baz :: String -> Integer -> Float 转换为 liftA2 baz :: IO String -> IO Integer -> IO Float。因此,这是一个与 foobar.

的输出类型相匹配的函数