为什么我不能用Haskell端口号中具有相同值的变量替换值?

时间:2013-09-19 12:18:37

标签: haskell ghci

这是一个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

为什么这不起作用?鉴于存储在Integer(或Word16中的变量,我正在阅读用户输入,因此我可以灵活处理),为什么我不能将其传递给PortNumber

2 个答案:

答案 0 :(得分:9)

正如the source所说:

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 - 类型和PortNumber - 构造函数(类型为PortID),这有点误导。)

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

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

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

答案 1 :(得分:5)

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

> let n = 1234 in PortNumber n

> let n = 1234
> PortNumber n

<interactive>:5:12:

这是因为ghci可以帮助你提前1行,当你在gchi中添加n,n :not: Num a => a时,它会成为n :: Integer。 Haskell没有类型转换。因此,您还可以使用PortNumber Word16Integer -> Word16fromInteger)进行类型转换:

>let n = 234
>PortNumber (fromInteger n)