What counts as a side-effect? Why isn't memory allocation a side-effect?
Asked Answered
H

2

9

I understand the appeal of pure functional languages like Haskell where you can keep track of side effects like disk I/O using monads.

Why aren't all system calls considered side effects? For example, heap memory allocation (which is automatic) in Haskell isn't tracked. And stack allocation could be a side effect, although I'm not sure it would be useful. Both of these change the overall state of the system.

So where is the line drawn for what is a side effect and what isn't? Is it simply at what's the most "useful"? Or is there a more theoretical foundation?

Howund answered 30/11, 2016 at 17:24 Comment(6)
I think the simplest answer is that if allocation was a side-effect, very few things would be “pure”, which sort of reduces the concept’s usefulness. Purity does not have one universal rigorous definition. I could imagine a language that did treat allocation as a side-effect and managed it through the type system, which could be highly useful on systems with small amounts of memory (i.e. embedded systems), but I don’t know of any such language currently.Capetian
Memory allocation is a side effect if you want to control when it happens. See IORef/STRef/FunPtr wrappers. It's just that if it's happening automatically then you can trust your compiler to be smart about it, so Haskell doesn't force you to worry about it.Corral
@AlexisKing As someone who occasionally has to write code for embedded systems, that would be a really interesting language to see implemented. I imagine it could be written as a DSL in Haskell, but it would be cool as a standalone language that compiled very efficiently.Sneer
What you cannot detect does not exist. You call a function, how do you detect if it allocated any memory?Radicel
You'll want to take a look at this discussion - the answer is "because we don't care". Yes, it would not be useful to consider the same values in two distinct memory locations to be different from each other.Infidelity
Related: Are side effects everything that cannot be found in a pure function?Doubtless
D
11

When reasoning about these things it has to be on a theoretic level and on language specification level and never on how it's actually done on hardware.

A programming language isn't really an actual implementation so unless you think about C og C++ that has memory allocation and syscall as a part of the language, the higher level languages where this is handled by the systems primitives it's not part of the language. If it isn't part of the language it cannot be a side effect.

Now an actual implementations machine code would never be pure since the way to pass arguments and to receive return values are to store in either registers or stack, both by mutation. Most of the concepts we use in all modern programming is translated down to arithmetic, flags, jumps, and memory access. Every CPU instruction except NOP mutates the machine. A program consisting of only NOP is not very useful.

Doorway answered 30/11, 2016 at 17:58 Comment(4)
All good answers, I think I confused the spec for Haskell with its implementation. Thanks. Now I wonder if there are any low level assembly/C like languages that do specify side effect semantics for things like allocation.Howund
CPU instruction evaluation has a hardware implementation as well, so NOP could (equally unhelpfully) be said to mutate the instruction pointer register.Thapsus
@thatotherguy True, but every instruction besides NOP also mutates something else than the program counter.Doorway
You might want to look at Rust, which has a statically checked model of "ownership" for allocated memory.Countershaft
H
9

Neither stack allocation nor heap allocation is something you can "do" or observe in Haskell. Therefore, it can't be counted as side effect. In a sense, the same goes for heating up the CPU, which is without doubt a recognizable physical effect of running pure Haskel code.

It so happens that certain implementations of Haskell on contemporary hardware and OS will allocate stack / heap in the course of running your code, but it is not observable from your code.

Harmony answered 30/11, 2016 at 17:48 Comment(1)
"It so happens that certain implementations of Haskell on contemporary hardware and OS will allocate stack / heap in the course of running your code" - and how!Midtown

© 2022 - 2024 — McMap. All rights reserved.