Type Variable Location in Transformers

老子叫甜甜 提交于 2020-01-23 17:02:23

问题


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

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

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) }

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)  }

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?


回答1:


I think the difference can be easily understood when m ~ IO:

s -> IO (a, s)

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.

Instead:

IO (s -> (a, s))

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.

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.

Instead,

s -> (IO a,  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).

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.

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



来源:https://stackoverflow.com/questions/49587122/type-variable-location-in-transformers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!