我写了一个简短的Haskell程序并编译它没有问题
import System.Random
func1=getStdRandom $ randomR ('A','Z')
main = do
print =<< func1
但如果我将元组更改为(1,100),我必须添加一个类型签名才能成功编译它。
import System.Random
func2 :: IO Int
func2=getStdRandom $ randomR (1,100)
main = do
print =<< func2
功能的类型不同。
Prelude System.Random> func1 = getStdRandom $ randomR ('A','Z')
Prelude System.Random> func2 = getStdRandom $ randomR (1,100)
Prelude System.Random> func3 = getStdRandom $ randomR (1,100) :: IO Int
Prelude System.Random> :t func1
func1 :: IO Char
Prelude System.Random> :t func2
func2 :: (Random a, Num a) => IO a
Prelude System.Random> :t func3
func3 :: IO Int
Prelude System.Random>
有人能告诉我为什么两个相似的元组(Char,Char)和(Int,Int)生成不同的类型签名函数?
如果我移动了该函数,它就不会编译。
import System.Random
main = do
print =<< getStdRandom $ randomR ('A','Z')
我不知道为什么“print =&lt;&lt; func1”有效但“print =&lt;&lt; getStdRandom $ randomR('A','Z')”如果func1和“getStdRandom $ randomR”不起作用('A','Z')“是一回事?
谢谢 EII
答案 0 :(得分:4)
当你在Haskell中编写一个数字文字时,它可能是Num
类型类的任何实例。这包括Float
,Double
,Int
,Integer
等内容。因此,编译器不知道您正在讨论哪个Num
,因此您必须指定你的意思是Int
。另一方面,字符文字总是Char
,所以不需要指定类型。
答案 1 :(得分:3)
有人能告诉我为什么两个相似的元组(Char,Char)和(Int,Int)生成不同的类型签名函数?
像(1, 100)
之类的元组没有类型(Int, Int)
,因为Haskell中的所有数字文字都是多态的,除非可以从上下文中推断出特定类型。
我不知道为什么“print =&lt;&lt; func1”有效但“print =&lt;&lt; getStdRandom $ randomR('A','Z')”如果func1和“getStdRandom $ randomR”不起作用('A','Z')“是一回事?
这是因为运营商优先。
print =<< getStdRandom $ randomR ('A','Z')
被解析为:
(print =<< getStdRandom) $ (randomR ('A','Z'))
你想要的是:
print =<< (getStdRandom $ randomR ('A','Z'))
答案 2 :(得分:2)
Prelude System.Random> getStdRandom $ randomR (1,100) :: IO Int
88
Prelude System.Random> getStdRandom $ randomR (1,100) :: IO Double
10.275865473218671
答案 3 :(得分:1)
有人能告诉我为什么两个相似的元组(Char,Char)和(Int,Int)生成不同的类型签名函数?
在Haskell中,整数文字实际上具有类型Prelude> :t 1
1 :: Num t => t
:
=>
t
之前的部分是类型约束。它表示类型Num
必须实现=>
类。 t
之后的部分是类型,在这种情况下只是1
。这意味着文字t
可以包含实现Num
类的任何类型a
。
类型类是一种表达类型支持一组函数的方式,例如在这种情况下,作为实例的每个类型fromInteger :: Integer -> a
(即实现)Num必须具有函数1
。 Haskell现在将fromInteger 1
到1
的所有整数文字去掉,其中Integer
的类型为{{1}}。