Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么可以';你能猜出正确的类型吗?_Haskell_Type Inference_Typeclass - Fatal编程技术网

Haskell 为什么可以';你能猜出正确的类型吗?

Haskell 为什么可以';你能猜出正确的类型吗?,haskell,type-inference,typeclass,Haskell,Type Inference,Typeclass,在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 ‘

在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
Prelude>fst(读“(1,2)”)
:20:6:
无法推断(读取b0)因使用“读取”而产生
从上下文(读a)
由它的推断类型绑定::Read a=>a
时间:20:1-18
类型变量“b0”不明确

问题是什么?

由于
读取
是一个多态函数,因此
读取“3”+4
可以工作,因为编译器知道您需要一个
Num
,因为您将
+
应用于
读取“3”
,如果编译器无法理解您需要的内容,则必须指定
读取
的类型,如下所示:

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

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

Prelude> :t read
read :: Read a => String -> a
正如您所看到的,它的返回值的类型必须是
Read
typeclass。但是,如果我们不使用该值,编译器将不知道它是什么类型

在这种情况下,我们可以添加
来指定其类型

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才能知道它的类型”,你的意思是你需要使用这个值,这样编译器才能知道它的类型吗?