Network
包中的PortNumber根本没有构造函数,其定义和文档如下(或请参考https://hackage.haskell.org/package/network-2.6.2.1/docs/Network.html):
data PortNumber
Use the Num instance (i.e. use a literal) to create a PortNumber value with
the correct network-byte-ordering. You should not use the PortNum constructor.
It will be removed in the next release.
instances
...
Num PortNumber
...
使我感到困惑的是它如何使用Num实例创建
PortNumber
?我知道PortNumber是Num类的实例,可以将其视为Num
,但是如何将Num实例(例如,文字10000
)视为PortNumber?构造具有构造函数为
PortNumber PortNumber
的PortID时,仅使用PortNumber 10000
似乎可以。这是怎么发生的? 最佳答案
如果查看source,您将看到以下内容:
newtype PortNumber = PortNum Word16 deriving (Eq, Ord, Typeable)
马上。
如果您查看文档,也会看到此警告:
不推荐使用的PortNum“不要使用PortNum构造函数。请使用Num实例。在下一发行版中将删除PortNum。”
这里的意思是
PortNumber
是instance of Num
,因此您可以使用fromInteger
-默认情况下,Haskell在看到1
,20
,...之类的整数时会执行此操作-这也是为什么Prelude> :t 666
666 :: Num a => a
因此,不用使用构造函数
PortNum 10000
,而只需使用10000
,它将在正确的上下文中自动成为PortNumber
(请参见下面的内容)对于
PortId
部分:PortNumber
,有一个PortId
构造函数(see source:data PortID =
Service String
| PortNumber PortNumber
| UnixSocket String
)-因此,如果您使用
PortNumber 10000
,则实际上确实在使用Int -> PortNumber -> PortId
路径,因为10000
(使用fromInteger
)被转换为PortNumber
,然后插入到构造函数PortNumber
中以获得PortId
除此之外,您可能会看到带有空数据定义的示例-但由于Haskell懒惰,您通常仍可以使用
undefined :: MyEmptyType
来获取无论如何都不会进行评估的地点的值。Fun with type functions中有一个很好的示例,其确切用法如下:
data Zero
data Succ n
class Nat n where
toInt :: n -> Int
instance Nat Zero where
toInt _ = 0
instance (Nat n) => Nat (Succ n) where
toInt _ = 1 + toInt (undefined :: n)