我试图通过编写一些我需要的东西来理解monad和箭头,当我读Haskell教程时,我觉得它们可能涉及人们正在谈论的内容,我想出了一个我能做的例子我的头脑很好:
newtype Stateful a b = Stateful { runStateful :: a -> (b, Stateful a b) }
stateful :: (a -> (b, Stateful a b)) -> Stateful a b
stateful = Stateful
-- executes a stateful computation, returning its result
evalStateful :: Stateful a b -> a -> b
evalStateful f x = fst $ runStateful f x
-- execStateful :: ??
execStateful = undefined
-- converts a stateful function to Stateful
close :: (s -> a -> (b, s)) -> s -> Stateful a b
close f s = stateful $ \x -> let (y, s') = f s x
in (y, close f s')
-- function composition
(<.>) :: Stateful a b -> Stateful b c -> Stateful a c
f <.> g = stateful $ \x -> let (y, f') = runStateful f x
(z, g') = runStateful g y
in (z, f' <.> g')
-- lifts a stateful computation to perform on lists
maps :: Stateful a b -> [a] -> [b]
maps f [] = []
maps f (x:xs) = let (x',f') = runStateful f x
in x' : maps f' xs
所以我的想法是你有一个函数,它接受并返回像(a -> s -> (b, s))
这样的状态,但是我们修改它以便不返回输出/状态元组而是返回一个输出/ X元组,其中X是与我们的初始功能相同的类型。所以有点像(a -> (b, a -> (b, ...)))
。我最初试图创建类似于State monad的东西,但是不是返回状态返回与自身相同的函数,状态部分应用(因此状态和它应用的函数保持耦合在一起)。
所以我想也许这就像State monad所做的那样,但我想要的一个用例就是能够将多个有状态函数链接在一起,每个函数都有自己独立于其他函数的状态。我没有想出一种方法来以优雅的方式将类型(s -> a -> (b, s))
和(s' -> b -> (c, s'))
的多个独立函数链接在一起,这不会导致返回的状态是一些丑陋的元组序列,如{{1你做的链越多,这让我觉得这可能比State monad更复杂。
我还读到了箭头,它用电路隐喻描述,并用于流处理,这符合我的设想。我看到有一个ArrowLoop,但是当我花了一段时间试图解决它时,似乎它更多地与聪明地使用懒惰而不是处理更新状态。然后我还读到IO monad使用某种类型系统技巧是不可避免的,这种感觉就像我用Stateful完成的那样;对于一个类型的Stateful不编码其内部状态的类型,因此很难(不可能?)推断(s''', (s'', (s', s)))
的类型。另一方面,我无法想出任何有意义的绑定运算符。
所以我不确定我在做什么。我认为它至少是一个仿函数,因为fmap只是在电路结束时组成一个任意函数,确保内部状态管理保持不变。我几乎确信自己的绑定可以用同样的方式定义,但每当我试图将这个想法具体化时,它就会崩溃。任何人都可以对我正在使用的内容有所了解吗?这是一些普通的monad还是箭头?一个特定的 monad或箭头?
此外,使用此方法是否存在明显的问题或改进?我希望内部状态能够使用ST monad,因为我设想内部状态由昂贵的就地操作组成。但我并不了解各种抽象概念,知道我的设计是否可扩展。
编辑:我需要做的一件事是确保原始的有状态函数不能被引用,因为它将引用旧状态而不是新更新的状态,我不知道如何去做这样做。基本上runStateful只能在Stateful数据类型上使用一次,然后你需要确保下次运行它时使用返回的execStateful
而不是原始的Stateful a b
。内部管道可以使意外地防止变得微不足道,但我不确定如何使它变得不可能。