变压器中类型可变的位置 [英] Type Variable Location in Transformers

查看:84
本文介绍了变压器中类型可变的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑State类型-或至少是简化版本:

Consider the State type - or at least a simplified version:

newtype State s a = State { runState :: s -> (a, s) }

现在,假设我们要导出StateT monad转换器. transformers对其定义如下:

Now, let's say we want to derive the StateT monad transformer. transformers defines it as follows:

newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }

在这里,m已放置在功能箭头的右侧,但在元组之外.但是,如果我们不知道正确的答案,则可以将m放在其他位置:

Here, the m has been placed on the right of the function arrow, but outside the tuple. However, if we didn't know the correct answer, we might instead put m somewhere else:

newtype StateT s m a = StateT { runStateT :: m (s -> (  a,  s)) }
newtype StateT s m a = StateT { runStateT ::    s -> (m a,  s)  }

很明显,transformers中的版本正确,但是为什么呢?更一般而言,在定义monad转换器时,如何知道内部" monad的类型变量放在何处?更概括地说,对于

Obviously the version in transformers is correct, but why? More generally, how does one know where to put the type variable for the 'inner' monad when defining a monad transformer? Generalising even more, is there a similar rule for comonad transformers?

推荐答案

我认为,当m ~ IO:

s -> IO (a, s)

是一种动作的类型,它可以读取当前状态s,根据该状态执行IO(例如,打印当前状态,从用户读取一行),然后生成新状态s,和返回值a.

is the type of an action which can read the current state s, perform IO depending on that (e.g. printing the current state, reading a line from the user), and then produce both the new state s, and a return value a.

相反:

IO (s -> (a, s))

是在不知道当前状态的情况下立即执行IO的操作的类型. IO全部结束后,它将返回一个纯函数,将旧状态映射为新状态并返回一个值.

is the type of an action which immediately performs IO, without knowing the current state. After all the IO is over, it returns a pure function mapping the old state into a new state and a return value.

这与先前的类型相似,因为新的状态和返回值可以取决于先前的状态和IO.但是,IO不能依赖于当前状态:例如,不允许打印当前状态.

This is similar to the previous type, since the new state and return value can depend both on the previous state and the IO. However, the IO can not depend on the current state: e.g., printing the current state is disallowed.

相反,

s -> (IO a,  s)

是读取当前状态s,然后根据该状态执行IO的操作的类型(例如打印当前状态,从用户读取一行),然后生成返回值a.取决于当前状态,而不是IO上的bot,将产生一个新状态.这种类型实际上与一对函数(s -> IO a, s -> s)同构.

is the type of an action which reads the current state s, and then performs IO depending on that (e.g. printing the current state, reading a line from the user), and then produce a return value a. Depdnding on the current state, bot not on the IO, a new state is produced. This type is effectively isomorphic to a pair of functions (s -> IO a, s -> s).

在这里,IO可以从用户那里读取一行,并据此生成返回值a,但是新状态不能依赖于该行.

Here, the IO can read a line from the user, and produce a return value a depending on that, but the new state can not depend on that line.

由于第一个变体比较笼统,我们希望将其作为状态转换器.

Since the first variant is more general, we want that as our state transformer.

我认为确定放置m的位置没有通用的规则:这取决于我们要实现的目标.

I don't think there's a "general rule" for deciding where to put m: it depends on what we want to achieve.

这篇关于变压器中类型可变的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆