5 ms·
It did to me. He slams go for not doing stuff the Haskell-way (e.g. pure code vs effectful code). This is not how you approach new things
by panpanna 6y ago
It did to me.
He slams go for not doing stuff the Haskell-way (e.g. pure code vs effectful code).
This is not how you approach new things
- eptcyka 6y agoThat is a single dubious point amongst some serious and in my opinion legitimate issues with the language.
- scottlocklin 6y agoComplaining about strict evaluation, the std lib not doing what he wants it to, the type system, the lack of heap profiler/threadscape, and .... demanding Golang handle zero values in his preferred way is basically him whining it ain't Haskell. I could blubber about it not having power conjunctions or self intervals or whatever if I wanted Golang to be J, which would be a similarly moronic roster of complaints. In reality golang is a basket of compromises like any other programming language. There's vastly more good stuff built in it than Haskell, despite Haskell being older and more theoretically amazing, so they must be doing something right. His only criticism that resonated with me was go get defaulting to head, which befuddled me when I first saw it, but that's a compromise too; one oriented to the large codebases that golang is designed for. It's actually a pretty good compromise compared to the propeller head Haskell dork "Things break backwards compatibility in Haskell, and the users just update their code because they know the library author did it for a reason." -aka this appears to be a statement from an academic wanker who obviously never had to ship on a timeline in his entire fucking life.
- simiones 6y agoThe type system complaints are somewhat in the area of "it should be more like Haskell", but the debugger, heap profiler and thread debugger ones are certainly not. Golang has extremely basic tools for anything beyond formatting/compiling compared to most modern languages. This is just a limitation of the current ecosystem, not something you can say has tradeoffs (except of course for the Go team's time/prioritization of features). Delve is getting better, but it has a LOT of ground to cover before it is half as useful as gdb or a java/C# debugger. Same goes for the profiling tools, especially on the CPU side.
- dmitriid 6y agoI've never really done Haskell, but I have Erlang, Java, C#, JS, TS and Erlang under my belt. I agree with everything the author said after having spend some time with Go.
- gwd 6y ago> He slams go for not doing stuff the Haskell-way (e.g. pure code vs effectful code). Heck, I come from a C background, and that's a complaint I have about Go. Sometimes you want to have a function accept a pointer to a large structure to avoid copying, but have the compiler prevent you from making any changes. In C you'd write "const"; in Go there's no way to do that.
- panpanna 6y agoSure, const is great to have. But Haskells view on this topic is far far more opinionated than just supporting 'const'.
- deleted 6y ago[deleted]
- Sharlin 6y agoI've never written Haskell or another pure functional language more than a couple of lines, but the more I write code the more convinced I become that the ability to reason about mutability and side effects is a major force multiplier in writing robust software.
- Chris_Newton 6y agoI agree that being able to reason about mutability and other effects is useful. However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. In a sibling comment, gwd mentioned const in C, which is one example of something in between. Rust’s ownership semantics and borrow checker are another.
- pwm 6y ago> However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. To elaborate this point I'd say that the most important practical use of all that "monad mumbo-jumbo" in Haskell is that you can tag your functions with what they can and can't do and then the type system tracks this for you: -- pure function f1 :: Text -> Int -- can fail f2 :: Text -> Maybe Int -- can read from some MyEnv record f3 :: Text -> Reader MyEnv Int -- can keep a set of bool as state around f4 :: Text -> State (Set Bool) Int etc... and of course to go nuclear: -- can do anything f5 :: Text -> IO Int The tracking part is that you can't call f5 from within f1, the type checker says no. It enforces separation between all these various effect boundaries. Also we don't have to stop here. A natural next step is defining exact effects one is after. For example say I want my function to be able to get some entity from a DB: -- any type that is an instance of Entity can identify itself by uuid class Entity e where identify :: e -> UUID -- The effect we want, ie. get an entity via its uuid class (Monad m, Entity e) => GetEntity e m where getEntityById :: UUID -> m (Maybe e) now we can say things like: data User = MkUser {uId :: UUID, uName :: Text} -- a User can identify itself instance Entity User where identify = uId -- as User is an Entity so we can get it via its uuid (if it exists) getUserById :: (GetEntity User m) => UUID -> m (Maybe User) getUserById = getEntityById Also notice how getUserById does not say anything about IO or a DB. All it states is that whatever context it will run in that context must know how to get a user via its uuid. You can then plug in whatever actual context you want, say: newtype Prod a = MkProd {unProd :: ReaderT ProdDB IO a} deriving newtype (Functor, Applicative, Monad, MonadReader ProdDB, MonadIO) -- get a user from a DB for real instance GetEntity User Prod where getEntityById :: UUID -> Prod (Maybe User) getEntityById eid = do ProdDB {..} <- ask -- query the DB, etc... or newtype Mock a = MkMock {unMock :: State (Map UUID User) a} deriving newtype (Functor, Applicative, Monad, MonadState (Map UUID User)) -- get a user from a mock DB instance GetEntity User Mock where getEntityById :: UUID -> Mock (Maybe User) getEntityById eid = gets (Map.lookup eid) All in all the programmer have fine-grained control over what various parts of their code can or can't do.