2025/03/21

Newest at the top

2025-03-21 21:23:21 +0100 <EvanR> again the functions don't cause any effects
2025-03-21 21:23:11 +0100 <EvanR> the f function is pure while the State action might be seen as "impure in context"
2025-03-21 21:22:28 +0100ash3en(~Thunderbi@89.56.182.235) ash3en
2025-03-21 21:22:18 +0100 <lambdabot> (1,1)
2025-03-21 21:22:16 +0100 <EvanR> > let f n = get >>= \s -> return (n+s) in runState (f 0 >> put 1 >> f 0) 0
2025-03-21 21:22:11 +0100 <lambdabot> (1,1)
2025-03-21 21:22:09 +0100 <EvanR> > let f n = get >>= \s -> return (n+s) in runState (f 0 >> put 1 >> f 0) 0
2025-03-21 21:22:08 +0100 <ski> "it was given the same argument, but returned something different both times" -- no, for reasons i tried to explicate, above
2025-03-21 21:21:28 +0100vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2025-03-21 21:21:19 +0100 <EvanR> I didn't write f right
2025-03-21 21:20:50 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-03-21 21:20:35 +0100 <ski> an action is a value, it is, on its own, just being, not peforming/doing/running/executing. only when an action is embedded in a larger action in a way that it'll get executed, when the larger one is, or when it's passed to a "run function" (like `runState') which executes the action, or (in the case of `IO') put as the definition of `main' (or entered into the interactor), does the action get executed
2025-03-21 21:20:35 +0100 <lambdabot> (0,1)
2025-03-21 21:20:33 +0100 <EvanR> > let f n = put (n+1) >> return 0 in runState (f 0 >> put 1 >> f 0) 0
2025-03-21 21:20:08 +0100wildsalander(~wildsalan@81-175-155-97.bb.dnainternet.fi) (Ping timeout: 272 seconds)
2025-03-21 21:18:18 +0100 <ski> "`f` returned `0+0=1` the first time, while it returned `1+0=1` the second time" -- no. `f' returned the same action (being a recipe expressing "yield zero added to the current state"), in both calls. but *executing*/invokking/running/performing this action, twoce, yields different results, in this situation
2025-03-21 21:16:23 +0100forell(~forell@user/forell) forell
2025-03-21 21:16:13 +0100 <ski> i agree that if "which returns the value of the state + its input" was true, then it would be impure. but it doesn't do that, and so wouldn't need to be impure (and actually isn't) on these grounds
2025-03-21 21:15:15 +0100 <ski> "which returns the value of the state + its input" -- it does not do this. `f' returns a value that is a `State Int'-action. the function `f' does not "returns the value of the state + its input". *invoking*/running/executing/performing this resulting action, will yield as a result "the value of the state + its input", yes
2025-03-21 21:13:39 +0100 <sim590> different both times, so `f` is impure.
2025-03-21 21:13:37 +0100 <sim590> ski: by that logic, I could say that a function `f :: Int -> State Int Int` which returns the value of the state + its input would be unpure because from what I CAN SEE, when I call `runState (f 0 >> put 1 >> f 0) 0`, `f` returned `0+0=1` the first time, while it returned `1+0=1` the second time. So, from what I can tell from the signature, it was given the same argument, but returned something
2025-03-21 21:13:36 +0100 <lambdabot> shachaf says: getLine :: IO String contains a String in the same way that /bin/ls contains a list of files
2025-03-21 21:13:36 +0100 <ski> @quote /bin/ls
2025-03-21 21:12:19 +0100 <ski> sim590 : does this help ?
2025-03-21 21:11:19 +0100 <EvanR> but I see it comes up in the guts of low level I/O stuff
2025-03-21 21:11:18 +0100 <ski> yes
2025-03-21 21:11:05 +0100 <EvanR> the RealWorld -> implementation is weird and not particular helpful to using IO normally
2025-03-21 21:10:33 +0100 <ski> and other Haskell implementations have internally represented `IO' in other ways (e.g. non-function ones, unlike the above)
2025-03-21 21:09:56 +0100 <ski> if you'd fool around with it, would allow you to express side-effecting computations, yes). this should be treated as an internal implementation detail, which just happens to be expressed in an internal language which happens to *look* like Haskell, for convenience
2025-03-21 21:09:51 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 268 seconds)
2025-03-21 21:09:50 +0100 <ski> GHC happens to represent `IO Char' as something like `RealWorld -> (Char,RealWorld)', internally, but this is carefully set up, and easy to mess up (largely, but not only, because Haskell has no support for checking uniqueness, unlike Clean and Mercury. even if that was added, other aspects of `IO' (concurrency, exceptions, ..) is not accurately explicitly reflected here ..), internal representation (which,
2025-03-21 21:06:09 +0100michalz(~michalz@185.246.207.193) (Remote host closed the connection)
2025-03-21 21:05:48 +0100 <ski> "behind the scene" or "under the (implementation covers)" doesn't matter. what matters is the interface presented to you, at the level of the language, what can be observed there, what reasoning laws you have available that preserve observable behaviour
2025-03-21 21:05:44 +0100 <EvanR> and if they did it would be bad
2025-03-21 21:05:34 +0100 <EvanR> just like 0 doesn't equal 1, () -> IO Char doesn't match IO Char
2025-03-21 21:05:11 +0100 <sim590> :D
2025-03-21 21:04:56 +0100 <sim590> That's what HE says.
2025-03-21 21:04:48 +0100 <EvanR> the type checker said so
2025-03-21 21:04:44 +0100 <lambdabot> with actual type ‘IO Char’
2025-03-21 21:04:44 +0100 <lambdabot> • Couldn't match expected type ‘() -> IO Char’
2025-03-21 21:04:44 +0100 <lambdabot> error:
2025-03-21 21:04:43 +0100 <EvanR> :t getChar :: () -> IO Char
2025-03-21 21:04:31 +0100 <sim590> Who says that `getChar :: IO Char` is not actually `getChar :: () -> IO Char` behind the scene and therefore, `getChar` is a function!
2025-03-21 21:04:31 +0100 <ski> machinery", but is enforced in Haskell) is what makes I/O effects explicit, not implicit, not on the side, not side-effects
2025-03-21 21:04:24 +0100 <ski> in Haskell, the effects of `getChar' and `putChar' are accounted for, explicitly, in the interfaces (type signatures), by the `IO' in `getChar :: IO Char' and `putChar :: Char -> IO ()' (and by `IO T' being a distinct type from `T', you can't implicitly treat a value of one as being a value of the other). this separation (which is similar in spirit to the old idea of "separate user interface from internal
2025-03-21 21:04:16 +0100 <EvanR> but while [5] or [[5]] are lists, 5 isn't a list
2025-03-21 21:03:50 +0100 <EvanR> might be what you were thinking
2025-03-21 21:03:46 +0100 <EvanR> you can "lambda wrap" any value you want to put another level of "function" around it though
2025-03-21 21:03:19 +0100 <EvanR> there's no argument or input to be had
2025-03-21 21:03:02 +0100 <EvanR> it's just a 5