从Haskell编程(http://www.cs.nott.ac.uk/~gmh/book.html)一书中,解析器的定义如下:
> type Parser a = String -> [(a,String)]
但是,从示例代码(http://www.cs.nott.ac.uk/~gmh/Parsing.lhs)开始,定义略有不同。
> newtype Parser a = P (String -> [(a,String)])
我发现此页面有所不同:https://wiki.haskell.org/Type#Type_and_newtype如下:
type引入了类型的同义词,并使用相同的数据构造函数。 newtype引入了类型的重命名,并要求您提供新的构造函数。
以下是我的问题:
P(...)
来封闭内容?答案 0 :(得分:7)
对于新类型,为什么使用
P(...)
来封闭内容?
任何newtype
声明的类型必须具有单个构造函数。在这种情况下,构造函数名为P
,其类型为
P :: (String -> [(a, String)]) -> Parser a
您也可以使用记录语法,因此它等同于
newtype Parser a = P { runParser :: String -> [(a, String)] }
或者如果您使用data
类型(在这种情况下,包装器在运行时不会轻易优化),它将非常相似:
data Parser a = P { runParser :: String -> [(a, String)] }
它需要为newtype提供新的构造函数,但我似乎没有从示例代码中找到一个。如何为newtype定义构造函数?可以不提供一个吗?
如上所述,newtype Parser
的构造函数名为P
,newtype
必须只有一个构造函数。
更进一步说明,type
关键字构造了一个简单的别名。例如,String
定义为
type String = [Char]
您可以在任何需要String
的功能中使用[Char]
,并且可以在任何需要[Char]
的功能中使用String
。由于FilePath
被定义为
type FilePath = String
然后,您可以使用FilePath
使用String
,因此可以使用[Char]
,反之亦然。这些只是减少更复杂类型的名称。我会说在实践中使用newtype
而不是type
更常见,除非在非常简单的情况下,仅仅因为它允许类型系统在您的软件中执行更多操作。 type
也有缺点,因为您需要语言扩展才能在instance
声明中使用它们,并且它们必须始终完全应用于其他表达式。 newtype
的缺点是你必须对它们进行大量包装/解包,但在使用真正复杂的程序时,这可能更有利。