0 haskell
所以,我有这个Haskell问题要解决:
定义一个mapIO函数,它接收一个函数f和一个输入和输出动作,a并产生一个输入和输出动作,当执行时,它执行给定的动作a并将应用程序返回f给返回a.
这是我的代码:
mapIO f a = do b <- a
return f(b);
Run Code Online (Sandbox Code Playgroud)
它编译但不起作用.当我尝试执行与以下执行示例相同的操作时,它不起作用.拜托,有人可以帮帮我吗?
Prelude Data.Char> mapIO even readLn
75
False
Run Code Online (Sandbox Code Playgroud)
在许多其他语言中,g(x)是将函数g应用于参数的语法x.在Haskell中,并置就足够了,所以g x适用g于x.巧合的是,这种方式g(x)是同样适用的有效语法g的值(x),这是一样的x,所以初学者它可能看起来g(x)是功能应用正确的语法.但事实并非如此,这种困惑在这里困扰着你.
在编写时return f(b),您可能会认为这意味着使用特殊语法return并且要返回的东西应该是函数应用程序f(b).但是,return它本身就是Haskell中的一个函数.所以它实际意味着应用于return函数f,然后将结果应用于术语(b).(在这个意义上,功能应用是"左联想".)
幸运的是,与其他关联性问题一样,函数应用程序关联性问题的修复是使用括号.所以:
return (f(b))
Run Code Online (Sandbox Code Playgroud)
或者,没有巧合正确的额外括号:
return (f b)
Run Code Online (Sandbox Code Playgroud)
这只留下了为什么它在return f(b)表单中"工作"(在编译和类型检查的意义上)的问题.这是一个高级主题; 但事实证明,函数也形成了一个Monadwith return = const,return f(b)实际上意味着const f(b),它抛弃了这个(b)术语.(旁白:除了被允许使用的函数实例Monad,我们也必须要使用的功能,比如Monad在这里,因为我们正在申请,return f到(b)的类型,return f必须是一个函数.)所以你的定义是一样的:
mapIO' f a = do b <- a
f
Run Code Online (Sandbox Code Playgroud)
那就是:先做a,扔掉它的结果,然后就f 好像它是另一个输入/输出动作.如果你检查推断的类型,mapIO你会发现它符合这种直觉:
mapIO :: Monad m => m b -> m t -> m b
Run Code Online (Sandbox Code Playgroud)
哎呦!