【问题标题】:Converting expression with >>= to do notation使用 >>= 将表达式转换为 do 表示法
【发布时间】:2023-03-05 22:17:01
【问题描述】:

我有以下代码

newtype State s a = State { runState :: s -> (s,a) }    
evalState :: State s a -> s -> a
evalState sa s = snd $ runState sa s

instance Functor (State s) where
  fmap f sa = State $ \s ->
    let (s',a) = runState sa s in
      (s',f a)

instance Applicative (State s) where
  pure a = State $ \s -> (s,a)

  sf <*> sa = State $ \s ->
    let (s',f) = runState sf s
        (s'',a) = runState sa s' in
      (s'', f a)

instance Monad (State s) where
  sa >>= k = State $ \s ->
    let (s',a) = runState sa s in
      runState (k a) s'

get :: State s s
get = State $ \s -> (s,s)

set :: s -> State s ()
set s = State $ \_ -> (s,())

bar (acc,n) = if n <= 0
              then return ()
              else
              set (n*acc,n-1)

f x = factLoop

factLoop =  get >>= bar >>= f

还有

 runState factLoop (1,7)

((5040,0),())

我正在尝试编写函数

 factLoop =  get >>= bar >>= f

使用 do 表示法

我试过了

 factLoop' =  do
                (x,y) <- get 
                h <-  bar (x,y) 
                return ( f h) 

但这并没有给出正确的类型,应该是State (Int, Int) ()

有什么想法吗?

谢谢!

【问题讨论】:

  • 养成为函数编写显式类型签名的习惯。它将帮助您看到f h 具有factLoop 具有的State (Integer, Integer) b 类型,因此您不需要return
  • BTW。更短、更清晰的伪代码——不是有效的 Haskell 代码。 :)

标签: haskell monads code-translation do-notation


【解决方案1】:

只需删除最后一行的return

factLoop' =  do
                (x,y) <- get 
                h <-  bar (x,y) 
                f h

您的原始代码中没有return,因此do 表示法版本中也应该没有。 do 符号只是“翻译”&gt;&gt;= 的用法,正如您已经完成的那样。

【讨论】:

    【解决方案2】:

    &gt;&gt;=infixl 1(左关联二元运算符),所以你真正拥有的是

    f x = factLoop
    
    factLoop =  get >>= bar >>= f
             =  (get >>= bar) >>= f
             =  (get >>= bar) >>= (\x -> f x)
             = do { x <- (get >>= bar)
                  ; f x }
             = do { _ <- (get >>= bar)
                  ; factLoop }
             = do { _ <- (get >>= (\x -> bar x))
                  ; factLoop }
             = do { _ <- do { x <- get 
                            ; bar x }
                  ; factLoop }
             = do { x <- get 
                  ; _ <- bar x 
                  ; factLoop }
    

    最后一个是因为 monad 结合律 ("Kleisli composition forms a category")。

    以您无需猜测的原则方式执行此操作。过了一会儿你当然会有所感觉,但在你这样做之前,正式一点会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-27
      • 2012-01-15
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      相关资源
      最近更新 更多