5 ms·
> It doesn't take "elaborate types" - just the question of "what interfaces does this need to support?" I suppose what counts as "elaborate" is a matter of opi
by thinkpad20 10y ago
> It doesn't take "elaborate types" - just the question of "what interfaces does this need to support?"
I suppose what counts as "elaborate" is a matter of opinion, but Haskell types in everyday code often become very involved and intricate. Here's an example from a piece of code I wrote a while back:
bindingsToSet :: Monad ctx =>
LEnvironment ctx ->
[Binding NExpr] ->
LazyValue ctx
bindingsToSet env bindings = do
let start = InProgress mempty
finish <- flip execStateT start $ forM_ bindings $ \case
NamedVar keys expr -> do
-- Convert the key expressions to a list of text.
keyPath <- lift $ mapM (evalKeyName env) keys
-- Insert the key into the in-progress set.
let lval = evalNExpr env expr
get >>= lift . insertKeyPath keyPath lval >>= put
Inherit maybeExpr keyNames -> forM_ keyNames $ \keyName -> do
-- Evaluate the keyName to a string.
varName <- lift $ evalKeyName env keyName
-- Create the lazy value.
let lval = evalNExpr env $ case maybeExpr of
Nothing -> mkSym varName
Just expr -> mkDot expr varName
-- Insert the keyname into the state.
get >>= lift . insertKeyPath [varName] lval >>= put
-- Convert the finished in-progress object into a LazyValue.
convertIP finish
Inside of this, we have a rather complex interplay between monad transformers, monadic bind, state, etc. Of course to some Haskell devs this might be no big deal to write, but for me, there's no way I could get all of that to be correct without a type checker. And to that end the Haskell type system and GHCi are an invaluable resource. However, I could very easily write equivalent code in python without a great deal of effort, and all of that crazy juggling of monad transformers would turn into very straightforward for loops and mutable assignment. Which isn't to argue that python is a superior solution to the problem, but...
> But in order for pdb to work, I have to have already written the code. It's inherently "push based", whereas in GHCi (or with typed-holes) I can "pull".
I disagree. In python you can start with a pdb that only gets so far, and figure out what y0u need to write based on inspecting the objects you have available in scope, testing out some functions on them, etc. In GHCi you can get help on what object is required to satisfy a type equation, but only after you first provide it with enough information that it has a meaningfully small set of free variables to solve. This of course doesn't mean that type holes are not super useful, but I would argue that their usefulness is in part due to how complicated Haskell's type system is. Of course, by the same token features like type holes turn that complexity into a strength. The functionality is incredibly useful in Haskell, no argument there -- but I don't find myself needing or missing it in python.
- codygman 10y agoIf you can provide the python version, please do. This seems like it could be a useful comparison.
- dllthomas 10y ago> I suppose what counts as "elaborate" is a matter of opinion I think you got the wrong bit of that. I wasn't saying that I don't sometimes wind up with elaborate types in Haskell, for which checking and inference is even more helpful. I was saying that even in the incredibly simple case where I just want to know an interface I still find it quite useful, and conspicuously absent in Python when I reach for it. > I disagree. In python you can start with a pdb that only gets so far, and figure out what y0u need to write based on inspecting the objects you have available in scope, testing out some functions on them, etc. What you describe here is push based. I need to come up with data, pass it into bits of the system, go through it forward until I get to the bit in question, and hope I've considered all the important bits. Again, a push based approach to answering these questions is often a good one, and Python probably has an edge there. I find that pull based is also often useful, and Python lacks it entirely. > In GHCi you can get help on what object is required to satisfy a type equation, but only after you first provide it with enough information that it has a meaningfully small set of free variables to solve. I ask these questions regularly, and don't recall it ever breaking down in this way... perhaps I'm just not understanding what you're getting at? > I don't find myself needing or missing it in python. Okay. I do. Repeatedly, every time I work in Python. Again, maybe I'm just faced with bad Python code? Maybe I've just done more Haskell, so built more of these habits? Maybe other pieces of our context are just different. Is your Python work usually more like greenfield development or are you needing to make changes to systems primarily built by other people? Or maybe it's just that we're different people :-P