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