Haskell 访问';a';在斯坦特

Haskell 访问';a';在斯坦特,haskell,Haskell,我试图用StateT编写一个函数,只是为了了解更多信息 在f中,我想访问StateT[Int]IO Int的最后一个类型参数中的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)

我试图用
StateT
编写一个函数,只是为了了解更多信息

f
中,我想访问
StateT[Int]IO Int
的最后一个类型参数中的
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(fx)[1,2,3]

要从GHCI获取以下信息,即打印
IO(Int,[Int])

(56, [2,3])
由于内部
a
,即
55
+1
,即从
[1,2,3]
返回
(56,[2,3])


如何编写上述函数,以访问
a

好的,下面是您想要的:

>>> 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
与给定类型的差异-即
f
StateT[Int]IO Int
类型值之间的函数,而不是该类型的值

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

f x = x >>= \i -> state (splitAt 1) >>= \[j] -> return (i + j)
或者,使用do表示法:

f x = do
  i <- x
  [j] <- state (splitAt 1)
  return (i + j)
所以现在我们不仅可以跑步

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

>>> runStateT (shiftAdd 55 >>= shiftAdd >>= shiftAdd)
(61,[])
它仍然不像它可能的那样惯用:

  • 我使用了
    splitAt
    (如果状态列表为空,它将抛出一个异常)使其不必要地部分化
  • 它不必要地特定(根本不使用IO,但我们不能将其用于其他基本单子)
解决这一问题让我们:

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,[])

好的,下面是你想要说的:

>>> 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
与给定类型的差异-即
f
StateT[Int]IO Int
类型值之间的函数,而不是该类型的值

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

f x = x >>= \i -> state (splitAt 1) >>= \[j] -> return (i + j)
或者,使用do表示法:

f x = do
  i <- x
  [j] <- state (splitAt 1)
  return (i + j)
所以现在我们不仅可以跑步

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

>>> runStateT (shiftAdd 55 >>= shiftAdd >>= shiftAdd)
(61,[])
它仍然不像它可能的那样惯用:

  • 我使用了
    splitAt
    (如果状态列表为空,它将抛出一个异常)使其不必要地部分化
  • 它不必要地特定(根本不使用IO,但我们不能将其用于其他基本单子)
解决这一问题让我们:

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,[])

我不清楚你在问什么。“在
f
中,我想访问
StateT[Int]IO Int
的最后一个类型参数中的Int”-最后一个类型参数是一元计算的返回类型,您不能从内部访问。你能发布一些你尝试过的代码和你得到的错误吗?也许你的意思是
f::Int->StateT[Int]IO Int
?在你运行计算之前,没有“内部
a
,即
55
”,除非你事先知道
x
返回某物的情况除外;在这种情况下,你应该首先通过
某件事
。很难在这里找到答案的起点,因为
fx
是键入错误的,正如其他人所指出的,我不清楚你在这里问什么。“在
f
中,我想访问
StateT[Int]IO Int
的最后一个类型参数中的Int”-最后一个类型参数是一元计算的返回类型,您不能从内部访问。你能发布一些你尝试过的代码和你得到的错误吗?也许你的意思是
f::Int->StateT[Int]IO Int
?在你运行计算之前,没有“内部
a
,即
55
”,除非你事先知道
x
返回某物的情况除外;在这种情况下,你应该首先通过
某个东西
。在这里很难找到答案的起点,因为
fx
是键入错误的,正如其他人所指出的,谢谢你提供了这个有用的详细答案!谢谢你的帮助,详细的回答!