newtype语法创建函数的原因



我看看这个声明:

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

以下是我的理解:

1( Parser被声明为具有类型参数a的类型

2( 您可以通过提供解析器函数来实例化Parser,例如p = Parser (s -> Nothing)

我观察到的是,我突然定义了一个函数名parse,它能够运行Parser。

例如,我可以运行:

parse (Parser  (s -> Nothing)) "my input" 

并得到CCD_ 4作为输出。

这个解析函数是如何用这个特定的签名定义的?这个函数是如何"知道"执行给它的Parser的?希望有人能澄清我的困惑。

谢谢!

当您编写newtype Parser a = Parser { parse :: String -> Maybe (a,String) }时,您将介绍三件事:

  1. 一个名为Parser的类型。

  2. Parser的一个术语级构造函数名为Parser。此功能的类型为

Parser :: (String -> Maybe (a, String)) -> Parser a

你给它一个函数,它将它封装在Parser

  1. 一个名为parse的函数,用于删除Parser包装并取回您的函数。此函数的类型为:
parse :: Parser a -> String -> Maybe (a, String)

ghci:中检查自己

Prelude> newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
Prelude> :t Parser
Parser :: (String -> Maybe (a, String)) -> Parser a
Prelude> :t parse
parse :: Parser a -> String -> Maybe (a, String)
Prelude>

毫无意义的是,术语级构造函数(Parser(和移除包装器的函数(parse(都是任意名称,不需要与类型名称匹配。例如,写是很常见的

newtype Parser a = Parser { unParser :: String -> Maybe (a,String) }

这清楚地表明CCD_ 15删除了解析函数的包装。但是,我建议您的类型和构造函数在使用newtypes时使用相同的名称。

这个函数如何"知道"执行给它的解析器

使用parse展开函数,然后使用"myInput"调用展开的函数。

首先,让我们看看一个没有记录语法的解析器newtype:

newtype Parser' a = Parser' (String -> Maybe (a,String))

这种类型的作用应该很明显:它存储一个函数String -> Maybe (a,String)。要运行这个解析器,我们需要创建一个新函数:

runParser' :: Parser' a -> String -> Maybe (a,String)
runParser' (Parser' p) i = p i

现在我们可以运行像runParser' (Parser' $ s -> Nothing) "my input"这样的解析器了。

但现在请注意,由于Haskell函数是curry函数,我们可以简单地删除对输入i的引用以获得:

runParser'' :: Parser' a -> (String -> Maybe (a,String))
runParser'' (Parser' p) = p

这个函数完全等同于runParser',但您可以用不同的方式来看待它:它不将解析器函数显式地应用于值,而是简单地获取一个解析器并从中获取解析器函数;然而,由于currying,runParser''仍然可以与两个参数一起使用。

现在,让我们回到您的原始类型:

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

您的类型和我的类型之间的唯一区别是,您的类型使用记录语法,尽管这可能有点难以识别,因为newtype只能有一个字段;该记录语法自动定义从Parser a中提取String -> Maybe (a,String)函数的函数parse :: Parser a -> (String -> Maybe (a,String))。希望其余部分应该是显而易见的:由于currying,parse可以与两个参数一起使用,而不是一个参数,这只会产生运行存储在Parser a中的函数的效果。换句话说,您的定义完全等同于以下代码:

newtype Parser a = Parser (String -> Maybe (a,String))
parse :: Parser a -> (String -> Maybe (a,String))
parse (Parser p) = p

最新更新