Pis*_*tor 0 haskell functional-programming newtype
我很难理解该newtype声明。我正在尝试 LYAH 中的练习:http://learnyouahaskell.com/functors-applicative-functors-and-monoids#the-newtype-keyword
并希望使用newtype来进行自定义类型实例化,Tofu Frank如下所示,遵循 LYAH 的配方:http://learnyouahaskell.com/making-our-own-types-and-typeclasses,但 newtype我自己添加了 -part 。
class Tofu t where
tofu :: j a -> t a j
instance Tofu Frank where
tofu x = Frank x
data Frank a b = Frank {frankField :: b a} deriving (Show)
newtype Frank a b = Frank{frankField :: (b a)} deriving Show
OUTPUT:
Multiple declarations of `Frank'
Declared at: tryouts.hs:563:1
tryouts.hs:572:1
Run Code Online (Sandbox Code Playgroud)
在 LYAH 的描述中newtype:http://learnyouahaskell.com/functors-applicative-functors-and-monoids#the-newtype-keyword指出:
使用 newtype 关键字代替 data 关键字。这是为什么呢?其一,newtype 速度更快。如果您使用 data 关键字来包装类型,则程序运行时所有包装和解包都会产生一些开销。但是如果你使用 newtype,Haskell 知道你只是用它来将现有类型包装成新类型(因此得名),因为你希望它内部相同但具有不同的类型。考虑到这一点,一旦 Haskell 解析出哪个值是什么类型,就可以摆脱包装和解包。
但是我newtype在这里是否误解了,只要前者在构造函数中只有一个字段(如我的示例中所示),newtype就不会覆盖现有类型吗?data如果我省略 -data声明部分,它似乎确实有效。
请注意, LYAH中的描述表示newtype使用代替。data这就是关键。两者data都newtype声明一个新的数据类型(Frank在您的情况下),并且您应该只使用其中之一,而不是同时使用相同的新数据类型。所以,你要么写:
data Frank a b = Frank {frankField :: b a} deriving (Show)
Run Code Online (Sandbox Code Playgroud)
如果你想Frank成为常规data类型,或者你写:
newtype Frank a b = Frank {frankField :: b a} deriving (Show)
Run Code Online (Sandbox Code Playgroud)
如果你想Frank成为一个newtype。
一般来说,Haskell 不支持“覆盖”(或重新定义或重新声明)数据类型,无论您使用data或newtype或某种混合。其他语言在这方面可能更灵活。例如,Python 将允许您定义一个class Frank,在某些代码中引用它,然后在更多代码中重新定义class Frank和使用新类:
class Frank:
def __init__(self):
self.name = "Frank Burns"
frank1 = Frank()
class Frank:
def __init__(self):
self.name = "Frankenstein"
frank2 = Frank()
print(frank1.name) # Frank Burns
print(frank2.name) # Frankenstein
Run Code Online (Sandbox Code Playgroud)
然而,Haskell 要求在一个地方定义新的数据类型。这类似于 Haskell 也要求只在一个地方定义一个(全局)函数。连续的多个定义行被视为单个定义的一部分:
-- this defines only one "frank"
frank 0 = "foo"
frank 1 = "bar"
Run Code Online (Sandbox Code Playgroud)
并且拒绝多个不连续的定义:
frank n = n*2
burns c = (c, c)
frank x = x-5 -- rejected
Run Code Online (Sandbox Code Playgroud)