在StateT中访问'a'

时间:2017-05-17 12:43:31

标签: haskell

我正在尝试使用StateT [Int] IO Int编写一个函数,只是为了了解更多信息。

f :: StateT [Int] IO Int f = state $ \xs -> update (error "I want a") xs update :: Int -> [Int] -> (Int, [Int]) update x [] = (x, []) update x (y:ys) = (x+y, ys) 中,我想访问let x = return 55 :: StateT [Int] IO Int的最后一个类型参数中的runStateT

*Main> :t runStateT
runStateT :: StateT s m a -> s -> m (a, s)

以下是我想称之为:

runStateT (f x) [1,2,3]

引用IO (Int, [Int])

(56, [2,3])

我希望能够运行它:

a

从GHCI获得以下内容,即55被打印:

+ 1

由于内部[1,2,3],即(56, [2,3])a,即来自$price = array($pricer['incvat']); ,会返回$price[] = $pricer['incvat'];

如何编写上述功能,访问button_style = ttk.Style() button_style.configure("button_style.TButton", relief=tk.RAISED, width = 20, padding=6, font=('Helvetica', 12) ) self.button = ttk.Button (self.myContainer1, text="Browse", style='button_style.TButton', command = self.browse_file) self.button.grid(row = 0,column = 3,padx=5, pady=10, ipadx=5, ipady=5)

1 个答案:

答案 0 :(得分:5)

好的,这就是你想要的:

>>> let x = return 55 ::  StateT [Int] IO Int
>>> runStateT (f x) [1,2,3]
(56, [2,3])

所以让我们从那里开始工作。

使用f,我们可以推断出它的类型 -

f :: StateT [Int] IO Int -> StateT [Int] IO Int

请注意问题中f的给定类型与[{1}}的差异 - 即fStateT [Int] IO Int类型值之间的函数,而不是该类型的值。

要定义f,我们需要(>>=) :: Monad m => m a -> (a -> m b) -> m b。这将允许我们输入类型为StateT [Int] IO Int的输入,并在Int输入计算上运行一些计算。

f x = x >>= \i -> state (splitAt 1) >>= \[j] -> return (i + j)

或者,使用do-notation:

f x = do
  i <- x
  [j] <- state (splitAt 1)
  return (i + j)

这给了我们我们想要的结果。

虽然这有效,但它非常非惯用。不是将monadic值作为输入传递给函数并将它们绑定到函数内部,而是定义使用常规值并返回monadic值的函数,使用bind运算符(>>=

因此定义

更为正常
shiftAdd :: Int -> StateT [Int] IO Int
shiftAdd i = do
  [j] <- state (splitAt 1)
  return (i + j)

所以现在我们不仅可以运行

>>> runStateT (shiftAdd 55) [1,2,3]
(56,[2,3])

但也

>>> runStateT (shiftAdd 55 >>= shiftAdd >>= shiftAdd)
(61,[])

它仍然不像以下那样惯用:

  • 我使用splitAt使它变得不必要(如果状态列表为空则会抛出异常)
  • 它是不必要的特定(根本不使用IO,但我们不能将它与其他基础monad一起使用)

解决这个问题让我们:

shiftAdd' :: (Monad m, Num a) => a -> StateT [a] m a
shiftAdd' i = state $ \js -> case js of
  [] -> (i, [])
  j : js -> (i + j, js)

哪种方法很好:

>>> runStateT (return 55 >>= shiftAdd') [1,2,3]
(56,[2,3])
>>> runStateT (return 55 >>= shiftAdd' >>= shiftAdd' >>= shiftAdd') [1,2,3]
(61,[])
>>> runStateT (return 55 >>= shiftAdd' >>= shiftAdd' >>= shiftAdd') []
(55,[])