如何正确使用>> =替换此代码中的do和< - ?

sti*_*ian 4 monads haskell monad-transformers

我有一个关于如何使用monad的问题.我有以下代码:

import System.Random
import Data.Random.Normal
import Graphics.EasyPlot
import Data.List
import Data.Function 

random' mean randomGen = zip x y 
    where                
       x = normals' (mean, 0.2) randomGen :: [Float]
       y = normals' (mean, 0.2) randomGen :: [Float]

randomW1 randomGen = [[x,y] | (x,y) <- random' 1.0 randomGen]

main = do  
    randomGen <- getStdGen
    let w1 = take 50 (randomW1 randomGen)
    print w1 
Run Code Online (Sandbox Code Playgroud)

它工作正常.但是,我认为它限制了绑定getStdGen外部的输出randomW1,并认为我能够通过写入getStdGen更直接地绑定randomW1

w1 = take 50 (randomW1 =<< getStdGen) 
Run Code Online (Sandbox Code Playgroud)

我相信我已经采用的>>==<<为"管道"一元结构连接在一起,以及替换的使用do<-.我在做的时候,我建议我发现它

Couldn't match type ‘IO’ with ‘[]’
Expected type: [StdGen]
  Actual type: IO StdGen  
Run Code Online (Sandbox Code Playgroud)

有没有办法用来>>=替换do<-代码?

chi*_*chi 7

main = do  
    w1 <- getStdGen >>= (return . take 50 . randomW1)
    print w1 
Run Code Online (Sandbox Code Playgroud)

(实际上不需要括号)

就个人而言,我不喜欢上面的风格,因为>>= (return . f)可以用fmap f更简单的方式实现,如下:

main = do  
    w1 <- (take 50 . randomW1) `fmap` getStdGen
    -- or: w1 <- take 50 . randomW1 <$> getStdGen
    print w1 
Run Code Online (Sandbox Code Playgroud)

删除最后一个<-,我们得到:

main = print . take 50 . randomW1 =<< getStdGen
Run Code Online (Sandbox Code Playgroud)

这是一个更系统的方法,逐步推导出最后一个.从头开始:

main = do  
    randomGen <- getStdGen
    let w1 = take 50 (randomW1 randomGen)
    print w1 
Run Code Online (Sandbox Code Playgroud)

内联w1:

main = do  
    randomGen <- getStdGen
    print (take 50 (randomW1 randomGen))
Run Code Online (Sandbox Code Playgroud)

Desugar do x <- m ; em >>= \x -> e.这是do语法的定义方式.

main = getStdGen >>= \randomGen -> print (take 50 (randomW1 randomGen))
Run Code Online (Sandbox Code Playgroud)

使用最后一个lambda的组合:

main = getStdGen >>= print . take 50 . randomW1
Run Code Online (Sandbox Code Playgroud)

  • @chi在GHC 7.10中,不再需要导入.顺便说一下,写第四种方式是'print = << take 50.randomW1 <$> getStdGen`,它非常巧妙地映射到原始do-block的不同部分. (5认同)
  • 只是在这里放下这个注释,有些人喜欢`<$>`````fmap \``. (2认同)