Haskell 声明 monad 在偶函数调用和奇函数调用上的不同行为
Haskell state monad different behaviour on even and odd function calls
我想制作一个函数,使用状态 monads 在奇数调用上加 5,在偶数调用上减去 6。
f 5 = 10
f 7 = 1
f 4 = 9
f 2 = -4
0 甚至 f 5 加 5。
1 是奇数所以 f 7 减去 6 等等。
我现在拥有的:
data Parity = Even | Odd deriving (Show, Eq)
not' :: Parity -> Parity
not' Even = Odd
not' Odd = Even
isOdd :: Int -> State Parity Int
isOdd x = state $ \(p) -> (if p == Odd then x + 5 else x - 6, not' p)
g n = do isOdd n
apply n = runState (g n) Even
我试过那样写,但每次使用 'apply' 时状态都没有保存。
它只加 5,因为最后是偶数。
我如何让它保存状态并且只初始化一次而不是每次?
我几天前写的这篇 可能会有帮助。
简而言之,State s
只是将 "stateful functions" f :: a -> b
模拟为纯函数 f :: (a,s) -> (b,s)
的一种便捷方式。为了适应 monad 框架,尽管这些是柯里化的,所以(大致)形式为 f :: a -> s -> (b,s)
。
类型State s b
大致是s -> (b,s)
,可以读作"a computation that returns a value b
and a final state s
and that requires an initial state s
to be run"。因此,单子函数 a -> State s b
是一个接受输入 a
的函数,并且可以 运行 给定初始状态 s
,以产生值 b
和最终状态 s
。
你的函数 isOdd
是,
isOdd x :: Int -> State Parity Int
isOdd x = state $ \p -> (if p == Odd then x + 5 else x - 6, not' p)
大致是,
isOdd' x :: Int -> Parity -> (Int,Parity)
isOdd' x p = (if p == Odd then x + 5 else x - 6, not' p)
还有你的电话,
apply n = runState (isOdd n) Even
大致是,
apply' n = isOdd' x Even
就是这样。您实际上是在计算
apply' n = --definition of apply'
isOdd' n Even
-- definition of isOdd'
(\x p -> (if p == Odd then x + 5 else x - 6, not' p)) n Even
-- application to the arguments `n` and `Even`
= (if Even == Odd then n + 5 else n - 6, not' Even)
-- simplifying
= (n - 6, Odd)
所以,
apply' n = (n - 6, Odd)
这是一个如何正确排序函数的示例,
f :: Int -> State Parity Int
f n = isOdd n >>= (\x -> isOdd x)
或等同于
f :: Int -> State Parity Int
f n = do x <- isOdd n
isOdd x
当您 运行 通过例如apply n = runState (f n) Even
您首先 运行 宁 isOdd n Even
,以获得结果 m
和一个新的最终状态,即 False
,然后 运行宁isOdd m False
。
我想制作一个函数,使用状态 monads 在奇数调用上加 5,在偶数调用上减去 6。
f 5 = 10
f 7 = 1
f 4 = 9
f 2 = -4
0 甚至 f 5 加 5。 1 是奇数所以 f 7 减去 6 等等。
我现在拥有的:
data Parity = Even | Odd deriving (Show, Eq)
not' :: Parity -> Parity
not' Even = Odd
not' Odd = Even
isOdd :: Int -> State Parity Int
isOdd x = state $ \(p) -> (if p == Odd then x + 5 else x - 6, not' p)
g n = do isOdd n
apply n = runState (g n) Even
我试过那样写,但每次使用 'apply' 时状态都没有保存。 它只加 5,因为最后是偶数。 我如何让它保存状态并且只初始化一次而不是每次?
我几天前写的这篇 State s
只是将 "stateful functions" f :: a -> b
模拟为纯函数 f :: (a,s) -> (b,s)
的一种便捷方式。为了适应 monad 框架,尽管这些是柯里化的,所以(大致)形式为 f :: a -> s -> (b,s)
。
类型State s b
大致是s -> (b,s)
,可以读作"a computation that returns a value b
and a final state s
and that requires an initial state s
to be run"。因此,单子函数 a -> State s b
是一个接受输入 a
的函数,并且可以 运行 给定初始状态 s
,以产生值 b
和最终状态 s
。
你的函数 isOdd
是,
isOdd x :: Int -> State Parity Int
isOdd x = state $ \p -> (if p == Odd then x + 5 else x - 6, not' p)
大致是,
isOdd' x :: Int -> Parity -> (Int,Parity)
isOdd' x p = (if p == Odd then x + 5 else x - 6, not' p)
还有你的电话,
apply n = runState (isOdd n) Even
大致是,
apply' n = isOdd' x Even
就是这样。您实际上是在计算
apply' n = --definition of apply'
isOdd' n Even
-- definition of isOdd'
(\x p -> (if p == Odd then x + 5 else x - 6, not' p)) n Even
-- application to the arguments `n` and `Even`
= (if Even == Odd then n + 5 else n - 6, not' Even)
-- simplifying
= (n - 6, Odd)
所以,
apply' n = (n - 6, Odd)
这是一个如何正确排序函数的示例,
f :: Int -> State Parity Int
f n = isOdd n >>= (\x -> isOdd x)
或等同于
f :: Int -> State Parity Int
f n = do x <- isOdd n
isOdd x
当您 运行 通过例如apply n = runState (f n) Even
您首先 运行 宁 isOdd n Even
,以获得结果 m
和一个新的最终状态,即 False
,然后 运行宁isOdd m False
。