简体   繁体   中英

Applicative instance for State - order of data flow

I am trying to implement Applicative instance for such a type:

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

I have some different ideas for (<*>) function. One way to implement it that comes to my mind is

(<*>) :: State s (a -> b) -> State s a -> State s b
State f <*> State s = State $ do
    (fa, fs) <- f
    let (sa, ss) = s fs
    return (fa sa, ss)

Or

(<*>) :: State s (a -> b) -> State s a -> State s b
State f <*> State s = State $ do
    (sa, ss) <- s
    let (fa, fs) = f ss
    return (fa sa, fs)

Which one (or does even any of them) is correct and why?

They both typecheck and differ only by "state" transformations order. I cannot find any good reason to prefer one over another...

First off, I'd recommend not using (monadic!) do syntax for defining an applicative instance like that, because it rather obscures what's happening. Here's your definitions using only standard functional syntax:

State f <*> State s = State $ \q
     -> let (fa, fs) = f q
            (sa, ss) = s fs
        in (fa sa, ss)

and

State f <*> State s = State $ \q
     -> let (fa, fs) = f ss
            (sa, ss) = s q
        in (fa sa, fs)

This also makes it clearer that there's not really any intrinsic evaluation order in an applicative instance (unlike a monad instance).

Both are reasonable. Note that you can get either of them from the other one:

x <*2> y = flip ($) <$> y <*1> x

It is a library convention, though, that the "effects" are performed left-to-right. Hence, the first version looks more familiar.

I believe both are correct because they don't violate any Applicative laws as far as I can see. However, the first is what is actually used. I think this is because of convention: it is expected that the effects of <*> 's left-hand arguments apply first, before its right-hand argument. Compare with IO , for example, where

(,) <$> readLn <*> getLine :: IO (Int, String)

prompts for an Int first, and then reads a String. It's nice to have State behave in a similar way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM