getStdRandom $ randomR返回什么?

时间:2016-10-05 09:05:38

标签: haskell random

我写了一个简短的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

4 个答案:

答案 0 :(得分:4)

当你在Haskell中编写一个数字文字时,它可能是Num类型类的任何实例。这包括FloatDoubleIntInteger等内容。因此,编译器不知道您正在讨论哪个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 11的所有整数文字去掉,其中Integer的类型为{{1}}。