Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
部分函数在Haskell中的应用_Haskell - Fatal编程技术网

部分函数在Haskell中的应用

部分函数在Haskell中的应用,haskell,Haskell,我刚开始学习Haskell,其中一个练习有点困难 具体来说,下面的内容并不像我预期的那样有效 parseNumber :: Parser LispVal parseNumber = (many1 digit) >>= (return $ Number . read) 除非我稍微改变一下 parseNumber :: Parser LispVal parseNumber = (many1 digit) >>= (\n -> return $ Number . rea

我刚开始学习Haskell,其中一个练习有点困难

具体来说,下面的内容并不像我预期的那样有效

parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (return $ Number . read)
除非我稍微改变一下

parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (\n -> return $ Number . read $ n)
我希望有人能解释为什么
返回$Number。read
的计算结果与我在第二个定义中明确创建的lambda函数不同,因为我认为这正是在无点样式代码中使用部分函数求值时所做的(显然不是!)


感谢您的帮助,希望这不是另一个初学者的单子问题…

这只是一个如何关联的问题。基本上,
$
只是一个用来写更少括号的操作符;这与在表达式末尾添加圆括号相同

利用这个想法,我们可以重写您的第二个示例:

parseNumber = (many1 digit) >>= (\n -> return (Number . read ( n)))
作为参考,带括号的原始表达式如下所示:

parseNumber = (many1 digit) >>= (return (Number . read))
因此,部分应用的等价物实际上是:

parseNumber = (many1 digit) >>= (\n -> (return (Number . read)) n)

基本上,组合多个
$
关联与您期望的不同。

看起来您想要:

parseNumber = (many1 digit) >>= (return . Number . read)
或者交替地

parseNumber = (many1 digit) `fmap` (Number . read)
Number。read
是一个函数
String->LispVal
因此
的类型返回$Number。read
解析器(String->LispVal)
,而您需要函数的类型是
String->Parser LispVal

转到定义--

现在你有了

return $ Number . read = ($) return (Number . read) -- (.) has higher precedence
                       = return (Number . read)
您使用的monad是
解析器
monad,因此它试图将解析后的值绑定到一个函数,该函数返回另一个函数的解析器(许多抽象层!)

相反,你想要的是

return . Number . read
这相当于你所写的,正如你所看到的

\n -> return $ Number . read $ n = \n -> return . Number . read $ n  -- definition of (.)
                                 = return . Number . read            -- eta reduction

最后,请注意,当您看到模式时

x >>= return . f
这总是可以替换为

fmap f x -- or liftM f x

i、 它表明您实际上根本没有使用
Monad
实例,而是使用较弱(更通用)的
函子
实例。

返回。号码。尽管阅读
应该有用。谢谢你的回答,尽管我有点理解$是如何与人交往的——我只是想象它在结尾留下了一些洞/地方,现在看起来很愚蠢。当我在方案中想象这(如果它有部分应用)时,我会考虑<代码>((+)1 2)< /C> > OK,因为<代码> + /代码>应用于没有参数本身,所以你得到<代码>(+ 1 2)< /代码>,当然,括号确实意味着代码> +(1, 2)< /代码>,这可能是我错误的地方,谢谢。这解决了我的问题,但我不认为它最好地回答了我的问题(它仍然很有帮助,因为我没有看到
Parser(a->b)
a->Parser b
之间的区别)一个彻底的答案,谢谢,但你没有以最快的速度回答。正如我在接受答案上解释的那样,问题是我想象在参数中留下了一个缺口(但在函数语言中,这只是愚蠢的,因为return的唯一参数可能是函数),所以接受答案更有用
fmap f x -- or liftM f x