Logs: liberachat/#haskell
| 2025-09-24 09:53:11 | <Enrico63> | Confirm. It is Applicative, but isn't a Monad. |
| 2025-09-24 09:54:13 | <Leary> | Enrico63: How about `hasThreeWords :: String -> Validation ()`? |
| 2025-09-24 09:54:16 | <Enrico63> | Yeah, I thought the same. As in, I feel like I'd need Monad for doing what is requested, but Validation is definitely not a Monad. |
| 2025-09-24 09:54:25 | <tomsmeding> | oh maybe the idea is that you use `orElse`? |
| 2025-09-24 09:55:04 | <tomsmeding> | perhaps not orElse since that throws away the error if it's a failure |
| 2025-09-24 09:55:38 | <Enrico63> | Leary, I've tried that, but I don't get, in the case of that failing, how to prevent the rest of the validation from running |
| 2025-09-24 09:56:02 | <tomsmeding> | I've never worked with Validation specifically, but `Validation e a -> a -> (a -> Validation e b) -> Validation e b` is implementable, I think -- where the loose 'a' argument is a default for when the first argument is a failure |
| 2025-09-24 09:56:13 | <tomsmeding> | not sure if Validation has a function with that functionality |
| 2025-09-24 09:56:52 | <Leary> | Enrico63: Are you sure you don't want it to keep running? |
| 2025-09-24 09:58:20 | <tomsmeding> | yeah what Leary says is the key point I think |
| 2025-09-24 09:58:26 | <Enrico63> | Leary, I'm gonna try |
| 2025-09-24 09:58:41 | <Leary> | (collecting as many warnings/errors as possible from the input is kinda the point of validation) |
| 2025-09-24 09:59:02 | <Unhammer> | So as a workaround to my TH woes I can put all my tests in src/, putting them in the main library. Is it possible to have two libraries in one .cabal file? stack doesn't seem to let me build project:lib:library2, only project:lib |
| 2025-09-24 09:59:09 | <Enrico63> | So you're saying that I should fire an error in case there's more than 3 words, but then I should disregard those additional words, rather than hard erroring, when doing the rest of the validation. |
| 2025-09-24 09:59:43 | <Leary> | Probably. It's a reasonable option anyway. |
| 2025-09-24 10:00:03 | <tomsmeding> | Unhammer: it is definitely possible to have multiple libraries in one .cabal file; at most one of them will be the "main" library (headed by `library`), the others will be sublibraries (headed by `library some-name`) |
| 2025-09-24 10:00:21 | <tomsmeding> | Unhammer: whether stack is happy with that I dunno, but cabal supports that first-class |
| 2025-09-24 10:00:22 | <Enrico63> | Leary, I see. In this case I just had the solution in front of me for the whole time. Let me try. |
| 2025-09-24 10:01:29 | <tomsmeding> | Enrico63: and do not there is bindValidation |
| 2025-09-24 10:01:53 | <tomsmeding> | which allows you, if I understand correctly, to "stop progressing" if an error occurred |
| 2025-09-24 10:02:05 | <tomsmeding> | but you may or may not want to actually use that, as Leary argued |
| 2025-09-24 10:05:02 | × | mud quits (~mud@user/kadoban) (Ping timeout: 258 seconds) |
| 2025-09-24 10:06:24 | → | CiaoSen joins (~Jura@2a02:8071:64e1:da0:5a47:caff:fe78:33db) |
| 2025-09-24 10:06:39 | → | mud joins (~mud@user/kadoban) |
| 2025-09-24 10:10:47 | <Enrico63> | Leary, but regarding the "keep running" approach, how am I gonna do that? If there's 3 words, I want to run `parseOp op <*> parseIntOrVar a <*> parseIntOrVar b`, being a, op, b the 3 words. But if there aren't 3 words... how am I gonna parse what's left? I could ignore the aditional words. But what if there are less, say 1 word. How do I proceed |
| 2025-09-24 10:10:47 | <Enrico63> | with the computations? |
| 2025-09-24 10:10:56 | <Unhammer> | OK, so `stack build project:lib` actually builds all libraries of the .cabal file. But for some reason, the linker error shows up again if I have `library testlib\nbuild-depends: applib` (where applib uses that C function). |
| 2025-09-24 10:11:18 | <Unhammer> | oh https://discourse.haskell.org/t/adding-template-haskell-library-produces-linker-error-on-alpine/13000 |
| 2025-09-24 10:11:27 | <Enrico63> | Leary, indeed, the testcase |
| 2025-09-24 10:11:27 | <Enrico63> | ``` |
| 2025-09-24 10:11:28 | <Enrico63> | parseExpression "k +" |
| 2025-09-24 10:11:28 | <Enrico63> | ``` |
| 2025-09-24 10:11:29 | <Enrico63> | expects this error |
| 2025-09-24 10:11:29 | <Enrico63> | ``` |
| 2025-09-24 10:11:30 | <Enrico63> | Expected: Errors ["Invalid expression: k +"] |
| 2025-09-24 10:11:30 | <Enrico63> | ``` |
| 2025-09-24 10:11:47 | <Enrico63> | So the parsing of `k` and `+` is not meant to have a chance to run |
| 2025-09-24 10:14:10 | × | infinity0 quits (~infinity0@pwned.gg) (Ping timeout: 255 seconds) |
| 2025-09-24 10:15:20 | <Enrico63> | Oh. I think the key is to use `empty`.. |
| 2025-09-24 10:15:42 | × | Vajb quits (~Vajb@n7nfchy4dz4j3x4yypz-1.v6.elisa-mobile.fi) (Ping timeout: 256 seconds) |
| 2025-09-24 10:16:13 | <Leary> | Neither `k` nor `+` are erroneous, so they wouldn't contribute to the error set either way; it's ambiguous whether parsing should proceed or not (perhaps intentionally so). |
| 2025-09-24 10:18:03 | <Enrico63> | Ok, I have a solution. This is the validator you suggested: |
| 2025-09-24 10:18:03 | <Enrico63> | ``` |
| 2025-09-24 10:18:04 | <Enrico63> | hasThreeWords :: String -> Validation () |
| 2025-09-24 10:18:04 | <Enrico63> | hasThreeWords s = case words s of |
| 2025-09-24 10:18:05 | <Enrico63> | (a:op:b:[]) -> pure () |
| 2025-09-24 10:18:05 | <Enrico63> | _ -> invalid $ "Invalid expression: " ++ s |
| 2025-09-24 10:18:06 | <Enrico63> | ``` |
| 2025-09-24 10:18:06 | <Enrico63> | and together with the others I've defined above, it can be used like this: |
| 2025-09-24 10:18:07 | <Enrico63> | ``` |
| 2025-09-24 10:18:07 | <Enrico63> | parseExpression :: String -> Validation Expression |
| 2025-09-24 10:18:08 | <Enrico63> | parseExpression str = hasThreeWords str *> |
| 2025-09-24 10:18:08 | <Enrico63> | case words str of |
| 2025-09-24 10:18:09 | <Enrico63> | (a:op:b:_) -> parseOp op <*> parseIntOrVar a <*> parseIntOrVar b |
| 2025-09-24 10:18:09 | <Enrico63> | _ -> empty |
| 2025-09-24 10:18:10 | <Enrico63> | ``` |
| 2025-09-24 10:19:14 | <Enrico63> | So if `hasThreeWords` passed, the computation proceeds as I had alrady done. The trick is that if that fails, then we just return `empty`, so we don't contribute to the list of errors, yet we don't hard-error nor we give a meaningless Ok. |
| 2025-09-24 10:20:41 | → | arandombit joins (~arandombi@2603:7000:4600:ffbe:15f4:44c6:cf8f:dc61) |
| 2025-09-24 10:20:41 | × | arandombit quits (~arandombi@2603:7000:4600:ffbe:15f4:44c6:cf8f:dc61) (Changing host) |
| 2025-09-24 10:20:41 | → | arandombit joins (~arandombi@user/arandombit) |
| 2025-09-24 10:25:52 | <Enrico63> | Thanks Leary and tomsmeding |
| 2025-09-24 10:33:10 | <Enrico63> | Ok, the solution from the site is a bit simpler, ahah: |
| 2025-09-24 10:33:11 | <Enrico63> | ``` |
| 2025-09-24 10:33:11 | <Enrico63> | parseExpression :: String -> Validation Expression |
| 2025-09-24 10:33:12 | <Enrico63> | parseExpression e = parse (words e) |
| 2025-09-24 10:33:12 | <Enrico63> | where parse [a1,op,a2] = parseOp op <*> parseArg a1 <*> parseArg a2 |
| 2025-09-24 10:33:13 | <Enrico63> | parse _ = invalid ("Invalid expression: " ++ e) |
| 2025-09-24 10:33:13 | <Enrico63> | ``` |
| 2025-09-24 10:34:35 | → | infinity0 joins (~infinity0@pwned.gg) |
| 2025-09-24 10:38:16 | → | wootehfoot joins (~wootehfoo@user/wootehfoot) |
| 2025-09-24 10:41:21 | → | Vajb joins (~Vajb@n73ytrjjz36ldo55g3k-1.v6.elisa-mobile.fi) |
| 2025-09-24 10:43:06 | × | wootehfoot quits (~wootehfoo@user/wootehfoot) (Ping timeout: 248 seconds) |
| 2025-09-24 10:45:46 | × | Vajb quits (~Vajb@n73ytrjjz36ldo55g3k-1.v6.elisa-mobile.fi) (Ping timeout: 248 seconds) |
| 2025-09-24 10:49:14 | × | trickard quits (~trickard@cpe-49-98-47-163.wireline.com.au) (Read error: Connection reset by peer) |
| 2025-09-24 10:49:27 | → | trickard_ joins (~trickard@cpe-49-98-47-163.wireline.com.au) |
| 2025-09-24 10:49:50 | × | mulk quits (~mulk@pd95144c3.dip0.t-ipconnect.de) (Remote host closed the connection) |
| 2025-09-24 10:51:42 | → | michalz joins (~michalz@185.246.207.197) |
| 2025-09-24 10:52:56 | × | michalz_ quits (~michalz@185.246.207.203) (Ping timeout: 258 seconds) |
| 2025-09-24 10:55:05 | → | Vajb joins (~Vajb@85-76-47-114-nat.elisa-mobile.fi) |
| 2025-09-24 10:58:37 | × | Enrico63 quits (~Enrico63@2a0b:e541:10d0:0:9efc:e8ff:fe24:3213) (Quit: Client closed) |
| 2025-09-24 11:03:40 | × | merijn quits (~merijn@77.242.116.146) (Ping timeout: 258 seconds) |
| 2025-09-24 11:06:21 | × | Vajb quits (~Vajb@85-76-47-114-nat.elisa-mobile.fi) (Ping timeout: 258 seconds) |
| 2025-09-24 11:06:44 | → | merijn joins (~merijn@77.242.116.146) |
| 2025-09-24 11:07:58 | × | CiaoSen quits (~Jura@2a02:8071:64e1:da0:5a47:caff:fe78:33db) (Ping timeout: 265 seconds) |
| 2025-09-24 11:10:59 | × | Athas quits (athas@2a01:7c8:aaac:1cf:d153:5501:dd03:4891) (Quit: ZNC 1.9.1 - https://znc.in) |
| 2025-09-24 11:11:11 | → | Athas joins (athas@sigkill.dk) |
| 2025-09-24 11:23:59 | → | craunts79 joins (~craunts@136.158.7.194) |
| 2025-09-24 11:24:44 | → | trickard___ joins (~trickard@cpe-51-98-47-163.wireline.com.au) |
| 2025-09-24 11:24:52 | × | arandombit quits (~arandombi@user/arandombit) (Ping timeout: 244 seconds) |
| 2025-09-24 11:25:23 | × | trickard_ quits (~trickard@cpe-49-98-47-163.wireline.com.au) (Ping timeout: 244 seconds) |
| 2025-09-24 11:26:13 | trickard___ | is now known as trickard |
| 2025-09-24 11:26:47 | → | CiaoSen joins (~Jura@2a02:8071:64e1:da0:5a47:caff:fe78:33db) |
| 2025-09-24 11:28:25 | → | Square joins (~Square4@user/square) |
| 2025-09-24 11:31:13 | → | Lord_of_Life_ joins (~Lord@user/lord-of-life/x-2819915) |
| 2025-09-24 11:31:14 | × | Inline quits (~Inline@ip-005-146-196-132.um05.pools.vodafone-ip.de) (Quit: Leaving) |
| 2025-09-24 11:31:35 | × | Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 244 seconds) |
| 2025-09-24 11:32:32 | Lord_of_Life_ | is now known as Lord_of_Life |
| 2025-09-24 11:32:37 | × | gabiruh quits (~gabiruh@vps19177.publiccloud.com.br) (Ping timeout: 244 seconds) |
| 2025-09-24 11:34:41 | × | xff0x quits (~xff0x@fsb6a9491c.tkyc517.ap.nuro.jp) (Ping timeout: 244 seconds) |
| 2025-09-24 11:35:43 | × | acidjnk quits (~acidjnk@p200300d6e71719544593b070e4f06c0e.dip0.t-ipconnect.de) (Ping timeout: 244 seconds) |
All times are in UTC.