Haskell

时间:2015-08-04 17:08:41

标签: haskell types

从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引入了类型的重命名,并要求您提供新的构造函数。

以下是我的问题:

  1. 对于新类型,为什么使用P(...)来封闭内容?
  2. 它需要提供带有newtype的新构造函数,但我似乎没有从示例代码中找到一个。如何为newtype定义构造函数?可以不提供一个吗?

1 个答案:

答案 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的构造函数名为Pnewtype必须只有一个构造函数。

更进一步说明,type关键字构造了一个简单的别名。例如,String定义为

type String = [Char]

您可以在任何需要String的功能中使用[Char],并且可以在任何需要[Char]的功能中使用String。由于FilePath被定义为

type FilePath = String

然后,您可以使用FilePath使用String,因此可以使用[Char],反之亦然。这些只是减少更复杂类型的名称。我会说在实践中使用newtype而不是type更常见,除非在非常简单的情况下,仅仅因为它允许类型系统在您的软件中执行更多操作。 type也有缺点,因为您需要语言扩展才能在instance声明中使用它们,并且它们必须始终完全应用于其他表达式。 newtype的缺点是你必须对它们进行大量包装/解包,但在使用真正复杂的程序时,这可能更有利。