Ser*_*kin 4 monads haskell types io-monad
我最近开始学习Haskell.我正在尝试编写一个选择数组的随机元素的程序:
import System.Random
randomInt :: (Int, Int) -> IO Int
randomInt range = randomRIO range :: IO Int
choseRandom :: [a] -> a
choseRandom list =
length list
>>=
(\l -> randomInt(0,l-1))
>>=
(\num -> (list !! num))
main :: IO ()
main = undefined
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Build FAILED
C:\Users\User\Haskell\Real\src\Main.hs: line 7, column 9:
Couldn't match expected type `IO Int' with actual type `Int'
In the return type of a call of `length'
In the first argument of `(>>=)', namely `length list'
In the first argument of `(>>=)', namely
`length list >>= (\ l -> randomInt (0, l - 1))'
Run Code Online (Sandbox Code Playgroud)
我做错了什么?我第一次交易单子很难
由于您在内部使用IO choseRandom,因此需要更改类型签名:
choseRandom :: [a] -> IO a
Run Code Online (Sandbox Code Playgroud)
其次,您不需要>>=用来获取列表的长度.>>=有类型
Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
类型length是[a] -> Int,所以类型length list是Int,不是monad.
您可以在致电时直接计算randomInt:
choseRandom :: [a] -> IO a
choseRandom list =
randomInt(0, length list) >>= (\num -> return (list !! num))
Run Code Online (Sandbox Code Playgroud)
这是一样的
choseRandom :: [a] -> IO a
choseRandom list = fmap (\num -> (list !! num)) (randomInt(0, length list))
Run Code Online (Sandbox Code Playgroud)
我第一次交易单子很难
是的,你通过避免语法支持使其变得更难.就这样写吧:
choseRandom list = do
let l = length list
num <- randomInt(0,l-1)
return (list !! num)
Run Code Online (Sandbox Code Playgroud)
这看起来不是更好吗?
现在到了这一点:randomRIO函数,如其类型所示,使用一些全局状态(可能是系统计时器).因此,您RandomRIO只能在IOMonad中使用结果.
另一种方法是初始化函数中的随机生成器main,并将此生成器传递给需要"随机"值的纯函数.