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
是键入错误的,正如其他人所指出的,谢谢你提供了这个有用的详细答案!谢谢你的帮助,详细的回答!