Newest at the top
| 2026-02-25 18:41:42 +0100 | <ski> | you never define local functions in a `where' or `let' ? |
| 2026-02-25 18:41:22 +0100 | <EvanR> | I have to admit I'm a never nester |
| 2026-02-25 18:40:01 +0100 | <ski> | (of course, you could simply hide, not export, `extraDef', from the module in question. but it's often nice to restrict scope more, to make sure it's evident that `extraDef' isn't used elsewhere in the module. and Haskell doesn't allow nested submodules ..) |
| 2026-02-25 18:38:19 +0100 | fgarcia | (~lei@user/fgarcia) fgarcia |
| 2026-02-25 18:38:09 +0100 | emaczen | (~user@user/emaczen) emaczen |
| 2026-02-25 18:38:04 +0100 | <ski> | (`fun ... and ...' is mutual recursive functions) |
| 2026-02-25 18:37:38 +0100 | <ski> | in SML, this would be `local fun extraDef ... = ... in fun foo ... = ... and bar ... = ... end' |
| 2026-02-25 18:37:00 +0100 | <ski> | in Haskell, you often have to resort to `(foo,bar) = (myFoo,MyBar) where myFoo = ...; myBar = ...; extraDef = ...', for this, which is ugly |
| 2026-02-25 18:36:10 +0100 | <ski> | a somewhat related thing is the `local <decls> in <decls> end' declaration, in SML. it declares the latter declarations (between `in' and `end'), while hiding the former ones, letting them be in scope in the latter ones, but not visible elsewhere |
| 2026-02-25 18:35:05 +0100 | emaczen | (~user@user/emaczen) (Remote host closed the connection) |
| 2026-02-25 18:34:49 +0100 | <ski> | yea, that's too invasive |
| 2026-02-25 18:34:19 +0100 | <haskellbridge> | <ijouw> Using current language, I would likely try to solve the dependency by making foo and bar a function and using liftA2 a lot and other pointfree stuff so cfg is never specified (but that will likely not make it readable). |
| 2026-02-25 18:30:17 +0100 | uli-fem | (~uli-fem@118.210.1.123) (Ping timeout: 248 seconds) |
| 2026-02-25 18:30:14 +0100 | <ski> | (btw, it would perhaps look neater to say `foo where cfg = defaultCfg' in place of `let cfg = defaultCfg in foo' .. but `where' is not an expression, attaches to defining equations (and `case' branches)) |
| 2026-02-25 18:27:59 +0100 | ski | prefers to pretend that extension does not exist |
| 2026-02-25 18:27:37 +0100 | <haskellbridge> | <ijouw> After enabling OverloadedRecordDot my brain parses that weirdly |
| 2026-02-25 18:27:08 +0100 | jmcantrell_ | (~weechat@user/jmcantrell) jmcantrell |
| 2026-02-25 18:26:36 +0100 | <ski> | ijouw : yes (that's why i wrote `foo' and `bar' in `..?cfg..foo.bar..', to indicate that those three would be allowed to occur free in that body) |
| 2026-02-25 18:25:59 +0100 | <ski> | nicer way to do it, but one would need to explain how `foo' could be in scope in the `barf' definition, and how `bar' could be in scope in the `frob' definition |
| 2026-02-25 18:25:52 +0100 | <ski> | (c) sometimes you want to do (a), but for mutually recursive functions, wanting to avoid passing around the *same* identical prefix parameters. so, i was pondering how one could possibly effect that, with a minimum of fuss. one attempt was to locally bind the respective parameters to an implicit `?cfg' (implementation detail), and then use that for the local, mutually recursive, definitions. there might be a |
| 2026-02-25 18:25:35 +0100 | uli-fem | (~uli-fem@118.210.1.123) |
| 2026-02-25 18:24:14 +0100 | <haskellbridge> | <ijouw> Do you intend foo = ..?cfg..foo..bar.. to be recursive? |
| 2026-02-25 18:23:02 +0100 | <ski> | (b) sometimes you have a general version of a function, and one version specialized to passing some default value for a parameter, as exemplified by `fooWith' & `foo'. as indicated, this could be done with conjunctive patterns, and `let'-`in'-patterns |
| 2026-02-25 18:21:05 +0100 | <ski> | explicit recursive call, passing some different value(s) for the prefix parameters, which would then bind the identifier (`loop') here to this *new* prefix, for that recursive call (this can e.g. be useful, if you're passing around an environment to an interpreter or type checker, mostly you want to pass along the same environment, but sometimes you want to change it) |
| 2026-02-25 18:20:59 +0100 | <ski> | (a) the `loop' and `map' case would be a way to give a *local* name for the function you're defining, applied to some prefix of the formal parameters, so that you don't need to repeat those parameters at recursive calls. this abbreviated form would naturally only be in scope inside the definition, and not elsewhere (because we would not know which value `f' would be bound to). it would be possible to use an |
| 2026-02-25 18:18:55 +0100 | merijn | (~merijn@77.242.116.146) (Ping timeout: 245 seconds) |
| 2026-02-25 18:16:50 +0100 | <ski> | this is about creative uses of patterns and scoping, to effect some convenience/elegance, for certain kinds of definition idioms |
| 2026-02-25 18:15:19 +0100 | <ski> | (it's not clear whether by `f g' you mean an expression, or a pattern, btw ..) |
| 2026-02-25 18:11:47 +0100 | <ski> | (this is not about dynamic scope) |
| 2026-02-25 18:11:34 +0100 | <ski> | no |
| 2026-02-25 18:10:37 +0100 | <haskellbridge> | <ijouw> You want (f g) to implicitly use another function named g that is in scope at use site? |
| 2026-02-25 18:10:29 +0100 | <ski> | (for the `loop' & `map' case above, `loop' doesn't explicitly bind the `f' parameter (and so must already assume `f' already comes from somewhere), so `loop' would just be in scope in the body, and not be in scope elsewhere `map' is in scope (where `f' isn't). in the `fooWith' & `foo' case, both conjuncts does bind `cfg', so both `fooWith' and `foo' makes sense here to use in a scope where `cfg' is not bound) |
| 2026-02-25 18:09:09 +0100 | sondr3 | (sondr3@2a01:7e01::f03c:92ff:fe06:7664) |
| 2026-02-25 18:08:59 +0100 | sondr3 | (sondr3@2a01:7e01::f03c:92ff:fe06:7664) (Server closed connection) |
| 2026-02-25 18:06:39 +0100 | <ski> | (issue is how to (reasonably) get both `foo' and `bar' in scope in both bodies ..) |
| 2026-02-25 18:06:08 +0100 | <ski> | to express this .. |
| 2026-02-25 18:06:01 +0100 | <ski> | bar@(barf cfg) = ..cfg..foo..bar.. |
| 2026-02-25 18:05:52 +0100 | <ski> | foo@(frob cfg) = ..cfg..foo..bar.. |
| 2026-02-25 18:05:31 +0100 | <ski> | maybe there's be some version of |
| 2026-02-25 18:04:29 +0100 | <ski> | it would be nice to be able to say something like `(frob,barf) = (\ ?cfg -> foo,\ ?cfg -> bar) where foo :: (?cfg :: ...) => ...; foo = ..?cfg..foo..bar..; bar :: (?cfg :: ...) => ...; bar = ..?cfg..foo.bar..' (having a common "config" argument in scope, over mutual recursion, avoiding repeating it in the recursive calls) |
| 2026-02-25 18:03:53 +0100 | lortabac | (~lortabac@mx1.fracta.dev) lortabac |
| 2026-02-25 18:03:39 +0100 | lortabac | (~lortabac@mx1.fracta.dev) (Server closed connection) |
| 2026-02-25 18:01:39 +0100 | misterfish | (~misterfis@84.53.85.146) (Ping timeout: 246 seconds) |
| 2026-02-25 17:59:41 +0100 | fgarcia | (~lei@user/fgarcia) (Ping timeout: 268 seconds) |
| 2026-02-25 17:58:21 +0100 | <ski> | where `let cfg = defaultCfg in foo' is a pattern that matches the input to `foo', and additionally binds `cfg' to `defaultCfg' (so that regardless of whether we use the `fooWith' or the `foo' entry point to the code, `cfg' will be in scope in the body) |
| 2026-02-25 17:57:05 +0100 | <ski> | yes. the second `@' would be the generalization of and/conjunction-pattern |
| 2026-02-25 17:56:31 +0100 | <lambdabot> | <hint>:1:32: error: Expression syntax in pattern: ?x |
| 2026-02-25 17:56:29 +0100 | <ski> | > let f :: Integer -> Integer; f ?x = ?x + 1 in f (f 3) |
| 2026-02-25 17:55:24 +0100 | EvanR | (~EvanR@user/evanr) EvanR |
| 2026-02-25 17:54:59 +0100 | EvanR | (~EvanR@user/evanr) (Server closed connection) |