如何在Haskell中手动部分应用功能

时间:2018-12-21 22:52:55

标签: haskell functional-programming currying

我无法理解以下代码的工作方式。我正在尝试遵循发现here的解析器示例。我以前使用过ReadP,想对解析器的工作方式有更深入的了解。我的问题不是特定于解析器,而是Haskell中的功能应用程序如何工作。这是代码:

module NanoParsec where

import Data.Char
import Control.Monad
import Control.Applicative

newtype Parser a = Parser { parse :: String -> [(a,String)] }

runParser :: Parser a -> String -> a
runParser m s =
    case parse m s of
        [(res, [])] -> res
        [(_, rs)]   -> error "Parser did not consume entire stream."
        _           -> error "Parser error."

item :: Parser Char
item = Parser $ \s ->
    case s of
        []     -> []
        (c:cs) -> [(c,cs)]

我知道还不需要导入。当我将其加载到ghci中时,它可以按预期工作:

Prelude> runParser item "m"
'm'
Prelude> runParser item "ms"
*** Exception: Parser did not consume entire stream.

所以在这里不足为奇。我束手无策的是如何将runParser应用于item。将runParser部分应用于item会产生类型String -> Char的函数:

Parser> :t runParser item
runParser item :: String -> Char

这是我尝试手动将runParser脱糖/应用到item的方式:

runParser item 
runParser Parser (\s -> ...)
(\m -> \s -> case parse m s of ...) Parser (\s -> ...)

这就是我被困住的地方。如果将m替换为Parser中的函数,则会得到parse parse s,这对我来说似乎是错误的。如何将runParser应用于item,以得到String -> Char类型的函数?我觉得我的attempt at desugaring不在了。

编辑:我错误地指出item适用于runParser;我在这里混淆了函数和变量。

2 个答案:

答案 0 :(得分:4)

也许这将使您朝正确的方向开始:

runParser item
= { definition of item }
runParser (Parser $ \s -> case s of ...)
= { definition of runParser }
(\m s -> case parse m s of ...) (Parser $ \s -> case s of ...)
= { substitute argument for m everywhere }
(\s -> case parse (Parser $ \s -> case s of ...) s of ...)
= { definition of parse }
(\s -> case (\(Parser f) -> f) (Parser $ \s -> case s of ...) s of ...)
= { substitute argument for f everywhere }
(\s -> case (\s -> case s of ...) s of ...)
= { substitute argument for s everywhere }
(\s -> case (case s of ...) of ...)

答案 1 :(得分:0)

我已经稍微修改了我的代码,它使用模式匹配而不是记录语法。这对于其他人可能更容易理解:

Aborted connection 27933 to db: 'wms_mysql' user: 'mysql' host: 'eifprdrds01.domain.com' (Got an error reading communication packets)
Aborted connection 26736 to db: 'wms_mysql' user: 'mysql' host: 'eifprdrds01.domain.com' (Got an error reading communication packets)
Aborted connection 27200 to db: 'wms_mysql' user: 'mysql' host: 'eifprdrds01.domain.com' (Got an error reading communication packets)
Aborted connection 27356 to db: 'wms_mysql' user: 'mysql' host: 'eifprdrds01.domain.com' (Got an error reading communication packets)
Aborted connection 29119 to db: 'wms_mysql' user: 'mysql' host: 'pc286.domain.com' (Got an error reading communication packets)
Aborted connection 16274 to db: 'wms_mysql' user: 'mysql' host: 'pc828.domain.com' (Got timeout reading communication packets)
Aborted connection 24916 to db: 'wms_mysql' user: 'mysql' host: 'pc830.domain.com' (Got an error reading communication packets)
Aborted connection 19357 to db: 'wms_mysql' user: 'mysql' host: 'pc830.domain.com' (Got an error reading communication packets)
Aborted connection 19343 to db: 'wms_mysql' user: 'mysql' host: 'pc830.domain.com' (Got an error reading communication packets)