使用 >>= 将表达式转换为 do 表示法
Converting expression with >>= to do notation
我有以下代码
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) ()
有什么想法吗?
谢谢!
只需删除最后一行的 return
:
factLoop' = do
(x,y) <- get
h <- bar (x,y)
f h
您的原始代码中没有 return
,因此 do
表示法版本中也应该有 none。 do
符号只是 "translates" 使用 >>=
,正如您已经完成的那样。
>>=
是 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")。
以不需要猜测的原则方式执行此操作。一段时间后,您当然会对此有所了解,但在您真正了解之前,保持正式会有所帮助。
我有以下代码
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) ()
有什么想法吗?
谢谢!
只需删除最后一行的 return
:
factLoop' = do
(x,y) <- get
h <- bar (x,y)
f h
您的原始代码中没有 return
,因此 do
表示法版本中也应该有 none。 do
符号只是 "translates" 使用 >>=
,正如您已经完成的那样。
>>=
是 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")。
以不需要猜测的原则方式执行此操作。一段时间后,您当然会对此有所了解,但在您真正了解之前,保持正式会有所帮助。