使用组合函子的应用实例

问题描述

我有两种形式的函数

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 _)。真的有办法吗?

解决方法

我认为应用函子是组成的,因此我可以将应用实例用于组合函子。

是正确的,但是假设我们采用f ~ (->) Int,则类型为(<$>) :: (a -> b) -> (Int -> a) -> (Int -> b)(<*>) :: (Int -> (a -> b)) -> (Int -> a) -> (Int -> b),但这与类型baz不匹配需要StringInteger,而foo返回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 = liftA2 baz <$> foo <*> bar

liftA2将在这里将baz :: String -> Integer -> Float转换为liftA2 baz :: IO String -> IO Integer -> IO Float。因此,此函数然后与foobar的输出类型匹配。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...