为什么不能 read 推断出正确的类型?
Why can't read deduce the correct type?
在 Haskell 中,我可以使用 read
.
从字符串中生成 Haskell 值
Prelude> read "1" + 3
4
我可以用fst
得到第一个元素
Prelude> fst (1,2)
1
但是,当我组合 read
和 fst
来获取第一个元素时出现错误:
Prelude> fst (read "(1,2)")
<interactive>:20:6:
Could not deduce (Read b0) arising from a use of ‘read’
from the context (Read a)
bound by the inferred type of it :: Read a => a
at <interactive>:20:1-18
The type variable ‘b0’ is ambiguous
有什么问题?
因为 read
是一个多态函数,所以 read "3" + 4
可以工作,因为编译器知道你想要 Num
因为你将 +
应用到 read "3"
,如果编译器不能弄清楚你想要什么,你必须指定类型 read
,像这样:
Prelude> let rd = read :: String->(Int,Int)
Prelude> rd "(1,2)"
首先,让我们看一下read
的类型签名:
Prelude> :t read
read :: Read a => String -> a
如您所见,它的 return 值必须具有 Read
类型类的类型。但是,如果我们不使用该值,编译器将不知道它是什么类型。
在这种情况下,我们可以添加::
来指定它的类型。
Prelude> read "5"
*** Exception: Prelude.read: no parse
Prelude> read "5" :: Int
5
同样,
Prelude> read "(1, 2)"
*** Exception: Prelude.read: no parse
Prelude> read "(1, 2)" :: (Int, Int)
(1,2)
Prelude> fst (read "(1,2)" :: (Int, Int))
1
编译器大部分时候可以推导出类型,但是当它遇到read "5"
时,它可能会混淆类型应该是Int
还是Float
或者其他什么.只有经过计算,Haskell才能知道它的类型。另一方面,Haskell有静态类型,所以它必须在编译前知道所有类型。
在 Haskell 中,我可以使用 read
.
Prelude> read "1" + 3
4
我可以用fst
得到第一个元素
Prelude> fst (1,2)
1
但是,当我组合 read
和 fst
来获取第一个元素时出现错误:
Prelude> fst (read "(1,2)")
<interactive>:20:6:
Could not deduce (Read b0) arising from a use of ‘read’
from the context (Read a)
bound by the inferred type of it :: Read a => a
at <interactive>:20:1-18
The type variable ‘b0’ is ambiguous
有什么问题?
因为 read
是一个多态函数,所以 read "3" + 4
可以工作,因为编译器知道你想要 Num
因为你将 +
应用到 read "3"
,如果编译器不能弄清楚你想要什么,你必须指定类型 read
,像这样:
Prelude> let rd = read :: String->(Int,Int)
Prelude> rd "(1,2)"
首先,让我们看一下read
的类型签名:
Prelude> :t read
read :: Read a => String -> a
如您所见,它的 return 值必须具有 Read
类型类的类型。但是,如果我们不使用该值,编译器将不知道它是什么类型。
在这种情况下,我们可以添加::
来指定它的类型。
Prelude> read "5"
*** Exception: Prelude.read: no parse
Prelude> read "5" :: Int
5
同样,
Prelude> read "(1, 2)"
*** Exception: Prelude.read: no parse
Prelude> read "(1, 2)" :: (Int, Int)
(1,2)
Prelude> fst (read "(1,2)" :: (Int, Int))
1
编译器大部分时候可以推导出类型,但是当它遇到read "5"
时,它可能会混淆类型应该是Int
还是Float
或者其他什么.只有经过计算,Haskell才能知道它的类型。另一方面,Haskell有静态类型,所以它必须在编译前知道所有类型。