2

这是一个展示该问题的 GHCI 会话:

Prelude> import Network
Prelude Network> PortNumber 1234
PortNumber 1234
Prelude Network> let n = 1234
Prelude Network> PortNumber n

<interactive>:5:12:
    Couldn't match expected type `PortNumber'
                with actual type `Integer'
    In the first argument of `PortNumber', namely `n'
    In the expression: PortNumber n
    In an equation for `it': it = PortNumber n

为什么这不起作用?给定一个存储在 an Integer(或 a Word16,我正在读取用户输入以便我可以灵活)中的变量,为什么我不能将它传递给PortNumber

4

2 回答 2

9

正如消息来源所说:

newtype PortNumber = PortNum Word16 deriving (Eq, Ord, Typeable)
-- newtyped to prevent accidental use of sane-looking
-- port numbers that haven't actually been converted to
-- network-byte-order first.

换句话说,他们不希望你搞乱PortNumber内部结构。(请注意,有PortNumber-type 和PortNumber-constructor(类型PortID),这有点误导。)

如果要在PortNumber(constructor) 中使用整数变量,则必须PortNumber手动将其转换为 (type)。幸运的是,它是 的一个实例Num,因此支持fromInteger

Prelude Network> let n = 234
Prelude Network> PortNumber (fromInteger n)
PortNumber 234

当您使用整数文字时,fromInteger编译器会自动添加以使您的生活更轻松。

于 2013-09-19T12:35:05.217 回答
5

Ghci 不喜欢多态类型,如果函数没有签名,ghci 会尝试使其成为单态。
但你仍然可以写

> let n = 1234 in PortNumber n

,

> let n = 1234
> PortNumber n

<interactive>:5:12:

发生这种情况是因为 ghci 帮助您提前 1 行,当您n :not: Num a => a在 gchi 中添加 n 时,它成功了n :: Integer。Haskell 没有类型转换。所以你也可以为 PortNumber Word16Integer -> Word16using fromInteger)进行类型转换:

>let n = 234
>PortNumber (fromInteger n)
于 2013-09-19T12:42:55.340 回答