Challenge 3: What Haskell's main Signature Encodes That Java's Doesn't — Possible Solution ==================================================================== -- Java's `public static void main(String[] args)` describes only the -- METHOD'S OWN SHAPE from the caller's perspective: it's public, it's -- static (callable with no object instance), it takes an array of -- Strings, and it returns nothing (void). Nothing in that signature -- says anything about what main actually DOES internally -- it could -- print to the console, read a file, open a network connection, -- mutate global state, or do nothing observable at all, and the -- signature would look identical in every case. The only way to know -- is to read the method's actual body. -- -- Haskell's `main :: IO ()` encodes something genuinely different: IO -- is a real type here, not just a return-type placeholder. Writing -- IO () tells the compiler -- and anyone reading the signature -- that -- main is specifically a computation that MAY perform real-world side -- effects (printing, reading input, file access, and so on), and that -- it produces no meaningful value once those effects are done ( () ). -- This isn't a comment or a convention; the Haskell type checker -- actively enforces it -- a PURE function (one with no IO in its own -- type) can never secretly call something IO-flavored and hide it, -- the way a "pure-looking" Java method secretly could. The type -- itself is proof of what kind of function you're looking at, before -- ever reading a single line of its body. WHY THIS WORKS AS AN ANSWER ------------------------------ This correctly identifies that Java's main signature describes only its own calling shape with zero information about internal behavior, while Haskell's main :: IO () is a real, compiler-enforced claim about side-effect capability -- matching the chapter's own central throughline about what the type system tracks.