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 +0100 | ash3en | (~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 +0100 | vanishingideal | (~vanishing@user/vanishingideal) vanishingideal |
2025-03-21 21:21:19 +0100 | <EvanR> | I didn't write f right |
2025-03-21 21:20:50 +0100 | merijn | (~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 +0100 | wildsalander | (~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 +0100 | forell | (~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 +0100 | merijn | (~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 +0100 | michalz | (~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 |