Gni*_*ruT 1 random haskell functional-programming deriving
我已经定义了以下数据类型:
data NewBool = Truth | Lie deriving (Show)
Run Code Online (Sandbox Code Playgroud)
我已经创建了一个函数,它应该返回一个随机的NewBool值
giveMeBool :: IO()
giveMeBool = do
bool <- randomIO :: IO NewBool
putStrLn("Your random boolean is"++ show bool)
Run Code Online (Sandbox Code Playgroud)
我在这里读到,我必须使NewBool成为Random的一个实例才能使用randomIO.所以我做到了这一点:
instance Random NewBool where
random g = case random g of
(r,g') | r < (1/2)= (Truth, g')
| otherwise= (Lie, g')
Run Code Online (Sandbox Code Playgroud)
真诚地,它只是我在另一篇文章中发现的复制和粘贴,但我不明白它是如何工作的?如何定义r的值和类型?谁能帮我?谢谢 ;)
既然random有类型(基本上)
random :: Random a => StdGen -> (a, StdGen)
Run Code Online (Sandbox Code Playgroud)
如果你通过它StdGen你有g,它会给你任何类型的实例化的值Random类型.编译器根据您的使用方式猜测您需要什么类型.在您的情况下,它会在片段中使用
r < (1/2)
Run Code Online (Sandbox Code Playgroud)
我们可以检查每个部分的类型
(<) :: Ord a => a -> a -> Bool
(1/2) :: Fractional a => a
Run Code Online (Sandbox Code Playgroud)
它们一起意味着完整的类型的r是
r :: (Random a, Fractional a, Ord a) => a
Run Code Online (Sandbox Code Playgroud)
这还不足以使Haskell继续进行,但由于这是数值类型中常见的情况(因为数字文字解析为模糊类型,而不是具体的数字类型)Haskell有一个"默认"系统.特别是,以下default配置生效(默认情况下)
default (Integer, Double)
Run Code Online (Sandbox Code Playgroud)
这意味着,如果有一个不明确型,由类的约束,并且或者Integer或Double可满足这些类,然后,在该顺序中,这些具体类型在被取代.在的情况下r,Double实例化Random,Ord以及Fractional因此编译器拾取r :: Double.
最后,我们考虑恰好在该区间上选择随机值的Random实例.这意味着它有50%的可能性大于,因此每个和构造函数将以相等的赔率被选中.DoubleDouble(0,1)(1/2)TruthLie
最后,为了真正实现Random NewBool它可能更好地从可用的非常相似的实例引导实例Bool.
instance Random NewBool where
random g = case random g of
(True, g') -> (Truth, g')
(False, g') -> (Lie, g')
Run Code Online (Sandbox Code Playgroud)
虽然这只有在你不想修改随机生成器的行为时才有效Random Bool.但是请注意,这里发生了类似的类型分辨率 - 除了它已经很简单,因为我在模式上匹配,True并且False立即意味着返回类型random g 必须是(Bool, StdGen).