Haskell 使用复合函子的应用实例
我有两个函数的形式Haskell 使用复合函子的应用实例,haskell,applicative,Haskell,Applicative,我有两个函数的形式 foo::Int->IO字符串 条::Int->IO整数 它们基本上存在于由(>)Int和IO组成的函子中。 现在,有一个类型的函数 baz::String->Integer->Float 我想使用如下应用程序语法将其提升到Int->IO\ucode>上下文 foobarbaz::Int->IO浮点 foobarbaz=baz foo bar 如果我这样做,编译器会对我大喊大叫 Couldn't match type `IO String' with `[Char]'
foo::Int->IO字符串
条::Int->IO整数
它们基本上存在于由(>)Int
和IO
组成的函子中。
现在,有一个类型的函数
baz::String->Integer->Float
我想使用如下应用程序语法将其提升到Int->IO\ucode>上下文
foobarbaz::Int->IO浮点
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
需要字符串和整数,而foo
返回一个IO字符串
和bar
一个IO整数
您可以利用提升baz
功能来使用IO
操作的结果:
import Control.Applicative(liftA2)
foobarbaz :: Int -> IO Float
foobarbaz = liftA2 baz <$> foo <*> bar
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
。因此,这是一个与foo
和bar
的输出类型相匹配的函数,谢谢!这是有道理的,基本上我需要一次提升一个函子。我还可以做(liftA2(liftA2-baz))foo-bar
。编译器不能只用一次提升就完成它有什么具体原因吗?@marcosh:有一次提升可以提升(>Int)
,但还有一次提升可以提升IO
。但是你是对的,你可以使用liftA2(lifta2baz)foobar
。提升总是提升到“一个”应用级别之上(由于类型系统,它总是最外层)。因此,它不会“递归”到更多级别,因为这可能会导致歧义。@marcosh要在一次提升中完成此操作,您可以使用Data.Functor.compose
显式地组合函子,但要付出一些新类型包装/展开的代价。