Logs: liberachat/#haskell
| 2021-06-09 12:20:58 | <int-e> | the text is imprecise because it focuses on the values of the list, ignoring its spine |
| 2021-06-09 12:21:19 | <boxscape> | yeah that's true |
| 2021-06-09 12:21:57 | → | tose joins (~tose@ip-85-160-36-186.eurotel.cz) |
| 2021-06-09 12:23:53 | → | ddellacosta joins (~ddellacos@86.106.121.83) |
| 2021-06-09 12:26:33 | <merijn> | Even without fusion laziness reduces the operational cost |
| 2021-06-09 12:26:43 | <merijn> | Since allocating and GCing in GHC is cheap |
| 2021-06-09 12:26:54 | <merijn> | not having to store the entire spine N times certainly matters |
| 2021-06-09 12:27:12 | <boxscape> | that's fair |
| 2021-06-09 12:27:43 | × | Torro quits (Torro@gateway/vpn/protonvpn/torro) (Quit: leaving) |
| 2021-06-09 12:28:33 | × | ddellacosta quits (~ddellacos@86.106.121.83) (Ping timeout: 252 seconds) |
| 2021-06-09 12:29:28 | <delYsid> | How do I run Haskell code at build-time to generate a datafile which will be includeed via file-embed? |
| 2021-06-09 12:30:01 | <delYsid> | I guess I need to hook into Setup.hs? But I didnt find any good examples yet. |
| 2021-06-09 12:32:42 | <merijn> | I would strongly advice on reconsidering at least one of those two >.> |
| 2021-06-09 12:33:55 | → | zebrag joins (~chris@user/zebrag) |
| 2021-06-09 12:35:39 | <delYsid> | care to elaborate? |
| 2021-06-09 12:35:58 | <merijn> | Hooking Setup.hs is super brittle |
| 2021-06-09 12:36:01 | <xerox> | delYsid: looks like it, I found this https://cabal.readthedocs.io/en/3.4/cabal-package.html#autogenerated-modules-and-includes and an example in the wild https://github.com/ArgonDesign/acov/search?q=buildversion |
| 2021-06-09 12:36:11 | <merijn> | It will break lots of things, such as doctests, etc. |
| 2021-06-09 12:36:35 | <merijn> | delYsid: What kinda data do you need to embed? |
| 2021-06-09 12:36:49 | <delYsid> | merijn: So is there a better way then Setup.hs? |
| 2021-06-09 12:37:42 | <merijn> | Not if you need an external file. But then, if you are gonna generate the file at compile time, do you even need an external file? |
| 2021-06-09 12:38:13 | <delYsid> | merijn: I lookup table, essentially... The data is in a text file, and I'd like to move the parser step from runtime to compile-time, since decoding via the Binary instance is way faster... |
| 2021-06-09 12:38:43 | <delYsid> | s/I/A/ |
| 2021-06-09 12:38:58 | <merijn> | delYsid: But you can just generate your lookup table at compile and embed that, rather than using file-embed, no? |
| 2021-06-09 12:39:43 | <delYsid> | I dont understand. I was planning to use decode . embedFile |
| 2021-06-09 12:39:46 | <merijn> | file-embed lets you embed external file as ByteString. But TemplateHaskell is much more powerful than that, you can simply convert to your final data structure at compile time and embed that data structure |
| 2021-06-09 12:39:59 | <merijn> | delYsid: Right, but that's like, the worst of both worlds? |
| 2021-06-09 12:40:09 | <merijn> | delYsid: The decode still happens at runtime |
| 2021-06-09 12:40:37 | <delYsid> | true, but its less worse then what I currently have, which is running megaparsec at runtime |
| 2021-06-09 12:41:11 | <delYsid> | But I get the idea, however, I have to admit, I am afraid of TH. Whenever I touched it, I almost went mad. |
| 2021-06-09 12:41:12 | <merijn> | delYsid: Is your text file generated or static? |
| 2021-06-09 12:41:23 | <merijn> | delYsid: file-embed *is* TH, though :p |
| 2021-06-09 12:41:43 | → | pbrisbin joins (~patrick@pool-72-92-38-164.phlapa.fios.verizon.net) |
| 2021-06-09 12:42:00 | <delYsid> | Well, the text file is sort of static, yeah. |
| 2021-06-09 12:42:17 | <delYsid> | It might change sometime, but its not autogenerated. |
| 2021-06-09 12:42:37 | <merijn> | ok, then I think your initial question was already confusing |
| 2021-06-09 12:43:06 | <delYsid> | likely, my questions here tend to do that. |
| 2021-06-09 12:43:27 | <merijn> | delYsid: Your question parses as: I want to generate a text-file using Haskell code, then embed that file using file-embed. Which is a major PITA, because that'd involve hooking Setup.hs and some kinda preprocessor setup |
| 2021-06-09 12:43:41 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:3429:27e5:c9dc:b9d2) |
| 2021-06-09 12:43:51 | <merijn> | delYsid: Whereas "I already have a file and want to embed that" is much less painful |
| 2021-06-09 12:44:12 | <merijn> | Because that can be done entirely in TH |
| 2021-06-09 12:45:52 | <merijn> | delYsid: If you have both "a text file" and "Haskell code that translates that file into whatever data structure you need at runtime", then doing that conversion in TH is fairly straightforward |
| 2021-06-09 12:45:54 | <delYsid> | Well, I know embedFile, and use it. All I want is to run the conversion from text to binary a build-time so that I can load a binary a runtime... I could as well commit the binary file to the repo, but thats ugly man. |
| 2021-06-09 12:46:38 | <merijn> | delYsid: Right, but how about this: Rather than than embedding the binary file, "read and convert" the text file at compile time and embed the resulting data structure |
| 2021-06-09 12:47:00 | <delYsid> | And pointers on getting me started on that? Its essentially a newtype'd HashMap... |
| 2021-06-09 12:47:27 | <merijn> | delYsid: Suppose your final (at runtime) data structure is "YourMap Foo Value" and you have "Text -> Either Error (YourMap Foo Value)" then things are "fairly" easy |
| 2021-06-09 12:47:42 | <merijn> | delYsid: Well, you'll want: https://hackage.haskell.org/package/template-haskell-2.17.0.0/docs/Language-Haskell-TH-Syntax.html#v:liftTyped |
| 2021-06-09 12:48:12 | <merijn> | delYsid: liftTyped turns a *value* (at TH runtime, i.e. compile time) into the TH *representation* of that value |
| 2021-06-09 12:48:34 | <delYsid> | oh, neat |
| 2021-06-09 12:48:41 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:3429:27e5:c9dc:b9d2) (Ping timeout: 268 seconds) |
| 2021-06-09 12:48:45 | <merijn> | delYsid: I've got a fun library showcasing this |
| 2021-06-09 12:48:48 | → | berberman_ joins (~berberman@user/berberman) |
| 2021-06-09 12:49:04 | × | berberman quits (~berberman@user/berberman) (Ping timeout: 272 seconds) |
| 2021-06-09 12:49:05 | <merijn> | delYsid: https://hackage.haskell.org/package/validated-literals |
| 2021-06-09 12:49:17 | <merijn> | delYsid: Which does partial conversions at compile time (and errors if they fail) |
| 2021-06-09 12:49:46 | <merijn> | delYsid: The Q (i.e. TH monad) is an instance of MonadIO, so you can just liftIO any filesystem code to run at compile time with no issue |
| 2021-06-09 12:50:05 | × | _________ quits (~nobody@user//x-7881368) (Remote host closed the connection) |
| 2021-06-09 12:50:23 | <delYsid> | So whats the type of my "compiler" function, then? |
| 2021-06-09 12:50:47 | <merijn> | delYsid: And then you could just write "lookup = $( liftIO (readFile path) >>= foo)" where 'foo' is a combination of liftTyped + your decode stuff |
| 2021-06-09 12:51:24 | → | lavaman joins (~lavaman@98.38.249.169) |
| 2021-06-09 12:51:31 | × | lavaman quits (~lavaman@98.38.249.169) (Remote host closed the connection) |
| 2021-06-09 12:51:42 | <merijn> | Simplest case would be "foo = liftTyped . decodeData" (but that's wrong if decodeData can return an Either/throw an exception, which you'd need to handle before liftTyped) |
| 2021-06-09 12:52:16 | <merijn> | but the validated-literals code has some examples of how to turn "Either Error a" into 'TExp a' that has a type error at compile time |
| 2021-06-09 12:52:41 | → | Tuplanolla joins (~Tuplanoll@91-159-68-239.elisa-laajakaista.fi) |
| 2021-06-09 12:52:45 | <merijn> | delYsid: For example: https://github.com/merijn/validated-literals/blob/master/ValidLiterals.hs#L110-L116 |
| 2021-06-09 12:53:00 | → | wonko joins (~wjc@62.115.229.50) |
| 2021-06-09 12:54:13 | <merijn> | delYsid: And then valid (or validInteger, etc.) can be used as splices like: https://github.com/merijn/validated-literals/blob/master/examples/Examples.hs#L24-L25 |
| 2021-06-09 12:55:29 | <delYsid> | [||val||] ugh, TH... |
| 2021-06-09 12:55:29 | → | fizbin joins (~fizbin@c-73-33-197-160.hsd1.nj.comcast.net) |
| 2021-06-09 12:55:31 | → | poljar1 joins (~poljar@93-139-68-198.adsl.net.t-com.hr) |
| 2021-06-09 12:55:34 | × | tose quits (~tose@ip-85-160-36-186.eurotel.cz) (Quit: WeeChat 3.0) |
| 2021-06-09 12:56:09 | <merijn> | delYsid: '[|| x ||]' just turns *value* 'x' into "an AST representing the value 'x'" |
| 2021-06-09 12:56:18 | <merijn> | delYsid: Since the output of TH is *an AST* |
| 2021-06-09 12:56:55 | → | zmt00 joins (~zmt00@user/zmt00) |
| 2021-06-09 12:56:57 | <merijn> | So "2" is just the value 2 in the TH code, but "[|| 2 ||]" is "an AST representing the syntax '2'" |
| 2021-06-09 12:57:14 | <delYsid> | my problem starts at liftTyped. I dont understand its type signature at all. Because I dont know what Code is... The Q monad confuses me. |
| 2021-06-09 12:58:06 | <merijn> | delYsid: Q monad is "IO + GHC" |
| 2021-06-09 12:58:30 | × | poljar quits (~poljar@93-143-149-172.adsl.net.t-com.hr) (Ping timeout: 250 seconds) |
| 2021-06-09 12:58:53 | <merijn> | delYsid: The Q is the "quasiquoting" monad. i.e. the context in which code that runs at compile time executes |
| 2021-06-09 12:59:13 | <merijn> | delYsid: Does the Exp type make sense to you? https://hackage.haskell.org/package/template-haskell-2.17.0.0/docs/Language-Haskell-TH.html#g:20 |
| 2021-06-09 12:59:45 | <merijn> | delYsid: i.e., that's just the datatype for Haskell's AST |
| 2021-06-09 12:59:52 | <xerox> | I used to be in the same camp til I found https://downloads.haskell.org/~ghc/8.10.3/docs/html/users_guide/glasgow_exts.html#template-haskell it is a very clear explanation I think |
| 2021-06-09 12:59:54 | × | fizbin quits (~fizbin@c-73-33-197-160.hsd1.nj.comcast.net) (Ping timeout: 252 seconds) |
| 2021-06-09 12:59:57 | <merijn> | (well, the expression part of the AST, anyway) |
| 2021-06-09 12:59:59 | × | cfricke quits (~cfricke@user/cfricke) (Ping timeout: 244 seconds) |
| 2021-06-09 13:00:17 | <merijn> | brb |
| 2021-06-09 13:00:23 | → | _________ joins (~nobody@user//x-7881368) |
| 2021-06-09 13:01:15 | → | alx741 joins (~alx741@181.196.69.18) |
| 2021-06-09 13:01:32 | × | brandonh quits (~brandonh@151.46.91.125) (Ping timeout: 250 seconds) |
| 2021-06-09 13:01:41 | → | ddellacosta joins (~ddellacos@89.46.62.63) |
| 2021-06-09 13:02:08 | → | favonia joins (~favonia@user/favonia) |
| 2021-06-09 13:02:10 | × | ddellacosta quits (~ddellacos@89.46.62.63) (Remote host closed the connection) |
| 2021-06-09 13:02:39 | → | ddellacosta joins (~ddellacos@89.46.62.63) |
| 2021-06-09 13:03:50 | → | fizbin joins (~fizbin@c-73-33-197-160.hsd1.nj.comcast.net) |
| 2021-06-09 13:04:01 | → | ddellaco_ joins (~ddellacos@86.106.121.65) |
| 2021-06-09 13:04:40 | <ski> | guest61 : well, i also suggested using `case'-`of' to pick apart the `parse' result, distinguishing between then successful and the failure case, rather than going on to use `fmap' all the time to manipulate the successful result. but also to use `case'-`of', instead of `==' and `/=' (and e.g. using `catMaybes' instead of `filter' and `fmap fromJust'). then i had a few cosmetic changes like removing |
| 2021-06-09 13:04:46 | <ski> | redundant brackets, removing all the `$'s, replacing `print' with `putStrLn' with `hPutStrLn stderr', factoring `pure' out of `maybe' |
| 2021-06-09 13:07:32 | × | ddellacosta quits (~ddellacos@89.46.62.63) (Ping timeout: 264 seconds) |
| 2021-06-09 13:10:39 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 272 seconds) |
| 2021-06-09 13:11:04 | → | favonia joins (~favonia@user/favonia) |
All times are in UTC.