为什么看不懂推断出正确的类型?

时间:2015-08-08 01:23:31

标签: haskell type-inference typeclass

在Haskell中,我可以使用read来创建Haskell值。

Prelude> read "1" + 3
4

我可以使用fst来获取第一个元素

Prelude> fst (1,2)
1

但是,当我将readfst合并到第一个元素时出现错误:

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

有什么问题?

2 个答案:

答案 0 :(得分:3)

由于read是一个多态函数,read "3" + 4有效,因为编译器知道您需要Num,因为您已将+应用于read "3",如果编译器无法弄清楚你想要什么,你必须指定read的类型,如下所示:

Prelude> let rd = read :: String->(Int,Int)
Prelude> rd "(1,2)"

答案 1 :(得分:1)

首先,让我们看一下read的类型签名:

Prelude> :t read
read :: Read a => String -> a

如您所见,其返回值必须具有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有静态类型,所以在编译之前必须知道所有类型