From jos.kusiek at tu-dortmund.de Fri May 1 07:38:53 2020 From: jos.kusiek at tu-dortmund.de (Jos Kusiek) Date: Fri, 1 May 2020 09:38:53 +0200 Subject: [Haskell-cafe] [Haskell-Cafe] How to deal with looped referencesinside instances? In-Reply-To: References: Message-ID: <202005010738.0417crq2026658@unimail.uni-dortmund.de> Hi, I don’t see any problem there. Why not just a pretty much do a one to one translation? class Engine e where showEng :: e -> String data Car e = Car { getId :: Int , getEng :: e } instance Engine e => Show (Car e) where show this = "Car with " ++ (showEng $ getEng $ this) data Steam = Steam { getCar :: Car Steam } instance Engine Steam where showEng this = "id " ++ (show $ getId $ getCar $ this) car :: Car Steam car = Car 42 $ Steam car And then just call „show car“. The should not be a problem with the looped reference. Greetings Jos Von: Daneel Yaitskov Gesendet: Freitag, 1. Mai 2020 01:33 An: haskell-cafe Betreff: [Haskell-cafe] [Haskell-Cafe] How to deal with looped referencesinside instances? {- Hi, I am trying to translate a Java sample with looped references below to Haskell. I've found 2 solutions, but both of them look ugly, because they require a helper class. So I am looking for an advice for best practices on working with looped references in polymorphic types. interface Engine { String showEng(); } class Car { int id; E eng; String show() { return "Car with " + eng.showEng(); } int getId() { return id; } } class Steam implements Engine { Car car; Stream(Car car) { this.car = car; } String showEng() { return "id " + car.getId(); } } Car car = new Car<>(); car.id = 42; car.eng = new Stream(car); car.show(); -} {-# LANGUAGE UndecidableInstances #-} -- Fix2 shortcoming class Car c where getId :: c -> Int class Engine e where showEng :: e -> String data SteamEng c = SteamEng c instance (Car c) => Engine (SteamEng c) where showEng (SteamEng c) = "id " ++ show (getId c) {- First solution is via ShowEng class. I don't know how to tell type checker that the type which is got after application of type function is instantiating Engine class?? instance (Engine eng) => Show (Car1 eng) where show (Car1 _ eng) = "Car1 with " ++ showEng eng -} data Car1 eng = Car1 Int (eng (Car1 eng)) class ShowEng f where showEng2 :: (Car a) => f a -> String instance ShowEng SteamEng where showEng2 = showEng {- A side note. Intuitive alternative for ShowEng which is not working! showEng2 = showEng means showEng2 gets Engine, but class HaveEngine f where cast :: (Car a) => f a -> f a instance HaveEngine SteamEng where cast = id ... instance (HaveEngine eng) => Show (Car1 eng) where show (Car1 _ eng) = "Car1 with " ++ (showEng (cast eng)) nor instance (HaveEngine eng) => Show (Car1 eng) where show (Car1 _ eng) = "Car1 with " ++ (showEng eng) -} instance Car (Car1 e) where getId (Car1 id _) = id instance (ShowEng eng) => Show (Car1 eng) where show (Car1 _ eng) = "Car1 with " ++ (showEng2 eng) c1 = Car1 42 (SteamEng c1) {- Second solution is removing argument from engine type parameter. -} data Car0 eng = Car0 Int eng instance Car (Car0 e) where getId (Car0 id _) = id instance (Engine eng) => Show (Car0 eng) where show (Car0 _ eng) = "Car0 with " ++ showEng eng {- in this case I have to avoid infinite type and introducing an extra wrapper and instantiating business logic classes for him. λ c0 = Car0 42 (SteamEng c0) :30:6: error: • Occurs check: cannot construct the infinite type: car ~ Car0 (SteamEng car) • In the expression: Car0 (SteamEng c0) In an equation for ‘c0’: c0 = Car0 42 (SteamEng c0) • Relevant bindings include c0 :: car (bound at :30:1) -} newtype Fix2 f g = Fix2 (f (g (Fix2 f g))) instance (Show (f (g (Fix2 f g)))) => Show (Fix2 f g) where show (Fix2 a) = show a {- λ c0 = Car0 42 (SteamEng (Fix2 c0)) :62:1: error: • No instance for (Car (Fix2 Car0 SteamEng)) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it -} instance (Car (f (g (Fix2 f g)))) => Car (Fix2 f g) where getId (Fix2 a) = getId a c0 = Car0 42 (SteamEng (Fix2 c0)) {- Thanks, Daniil -} _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From icfp.publicity at googlemail.com Fri May 1 19:05:05 2020 From: icfp.publicity at googlemail.com (Sam Tobin-Hochstadt) Date: Fri, 01 May 2020 15:05:05 -0400 Subject: [Haskell-cafe] ICFP 2020 will be held ONLINE Aug 23-28 Message-ID: <5eac72e1ecab0_5b6e2b07d78345b449227@homer.mail> The ICFP 2020 organizers would like to announce that the conference and co-located events, originally scheduled for August 23-28, in Jersey City, New Jersey, will now be held online during the same dates. Further information for presenters, authors, attendees, sponsors, and the ICFP community will be provided as it becomes available. The ICFP Organizing Committee From johannes.waldmann at htwk-leipzig.de Sat May 2 15:43:40 2020 From: johannes.waldmann at htwk-leipzig.de (Johannes Waldmann) Date: Sat, 2 May 2020 17:43:40 +0200 Subject: [Haskell-cafe] cost of Text.Parsec.Expr Message-ID: Dear Cafe, I use `buildExpressionParser` https://hackage.haskell.org/package/parsec-3.1.14.0/docs/Text-Parsec-Expr.html#v:buildExpressionParser with a table similar to https://hackage.haskell.org/package/haskell-src-exts-1.23.0/docs/Language-Haskell-Exts-Fixity.html#v:preludeFixities and I find it's somewhat expensive. I think the algorithm makes me pay for each operator that is in the table even when just a few of them are actually in the input. (I removed from the table those that don't appear in my test cases, and it got faster.) Certainly this is known? What could be done about it? What does Megaparsec do? It seems that Text.Megaparsec.Expr vanished from version 6 to version 7. A classical shift/reduce algorithm would help (?) but not with the given type of table, which does not allow to parse an operator just once, and then look up its precedence. - J.W. From zemyla at gmail.com Sat May 2 17:17:33 2020 From: zemyla at gmail.com (Zemyla) Date: Sat, 2 May 2020 12:17:33 -0500 Subject: [Haskell-cafe] cost of Text.Parsec.Expr In-Reply-To: References: Message-ID: You can cheaply reduce the cost of some of it by combining operators with the same precedence and associativity. For instance, instead of doing as the example says and having separate table entries for "+" and "-", have one entry that parses a "+" or "-" and returns the appropriate operator. On Sat, May 2, 2020, 10:44 Johannes Waldmann < johannes.waldmann at htwk-leipzig.de> wrote: > Dear Cafe, > > I use `buildExpressionParser` > > https://hackage.haskell.org/package/parsec-3.1.14.0/docs/Text-Parsec-Expr.html#v:buildExpressionParser > > with a table similar to > > https://hackage.haskell.org/package/haskell-src-exts-1.23.0/docs/Language-Haskell-Exts-Fixity.html#v:preludeFixities > > and I find it's somewhat expensive. I think the algorithm > makes me pay for each operator that is in the table > even when just a few of them are actually in the input. > (I removed from the table those that don't appear in my test cases, > and it got faster.) > > Certainly this is known? What could be done about it? > What does Megaparsec do? It seems that Text.Megaparsec.Expr > vanished from version 6 to version 7. > > A classical shift/reduce algorithm would help (?) > but not with the given type of table, which does not allow > to parse an operator just once, and then look up its precedence. > > - J.W. > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From godzbanebane at gmail.com Sat May 2 22:26:48 2020 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Sun, 3 May 2020 01:26:48 +0300 Subject: [Haskell-cafe] cost of Text.Parsec.Expr In-Reply-To: References: Message-ID: Text.Megaparsec.Expr has been moved to https://hackage.haskell.org/package/parser-combinators-1.2.1/docs/Control-Monad-Combinators-Expr.html ====== Georgi -------------- next part -------------- An HTML attachment was scrubbed... URL: From Graham.Hutton at nottingham.ac.uk Mon May 4 12:30:47 2020 From: Graham.Hutton at nottingham.ac.uk (Graham Hutton) Date: Mon, 4 May 2020 12:30:47 +0000 Subject: [Haskell-cafe] Journal of Functional Programming - Call for PhD Abstracts Message-ID: ============================================================ CALL FOR PHD ABSTRACTS Journal of Functional Programming Deadline: 31st May 2020 http://tinyurl.com/jfp-phd-abstracts ============================================================ PREAMBLE: Many students complete PhDs in functional programming each year. As a service to the community, twice per year the Journal of Functional Programming publishes the abstracts from PhD dissertations completed during the previous year. The abstracts are made freely available on the JFP website, i.e. not behind any paywall. They do not require any transfer of copyright, merely a license from the author. A dissertation is eligible for inclusion if parts of it have or could have appeared in JFP, that is, if it is in the general area of functional programming. The abstracts are not reviewed. Please submit dissertation abstracts according to the instructions below. We welcome submissions from both the PhD student and PhD advisor/supervisor although we encourage them to coordinate. ============================================================ SUBMISSION: Please submit the following information to Graham Hutton by 31st May 2020: o Dissertation title: (including any subtitle) o Student: (full name) o Awarding institution: (full name and country) o Date of PhD award: (month and year; depending on the institution, this may be the date of the viva, corrections being approved, graduation ceremony, or otherwise) o Advisor/supervisor: (full names) o Dissertation URL: (please provide a permanently accessible link to the dissertation if you have one, such as to an institutional repository or other public archive; links to personal web pages should be considered a last resort) o Dissertation abstract: (plain text, maximum 350 words; you may use \emph{...} for emphasis, but we prefer no other markup or formatting; if your original abstract exceeds the word limit, please submit an abridged version within the limit) Please do not submit a copy of the dissertation itself, as this is not required. JFP reserves the right to decline to publish abstracts that are not deemed appropriate. ============================================================ PHD ABSTRACT EDITOR: Graham Hutton School of Computer Science University of Nottingham Nottingham NG8 1BB United Kingdom ============================================================ This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please contact the sender and delete the email and attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. Email communications with the University of Nottingham may be monitored where permitted by law. From ganesh at earth.li Mon May 4 18:53:12 2020 From: ganesh at earth.li (Ganesh Sittampalam) Date: Mon, 4 May 2020 19:53:12 +0100 Subject: [Haskell-cafe] Windows Haskell CI In-Reply-To: References: <20200427125749.GB15031@extensa> <063f39587e3e404334c2412b7f4ff2eddb194612.camel@joachim-breitner.de> Message-ID: On 29/04/2020 23:20, Ben Franksen wrote: >> It doesn't help for people who want to develop _on_ windows, but at >> least releasing _for_ windows is prettty painless this way. > > Indeed, developing on Windows is something we'd very much like to avoid. As another darcs developer, I'm ambivalent about it. Windows certainly has its pain points but it's the native OS on my primary machine and developing in that OS rather than inside a VM does make many things simpler. But it's pretty clear no-one else wants to get too close :-) > But what we definitely need is to be able to run our test suite on > Windows; and a significant part of that are a couple hundred bash > scripts. If your approach could handle that, I'd be interested to know more. Given how slow bash scripts are on Windows, another strategy would be to simply rewrite them in something else, e.g. something we can directly interpret in Haskell. But whatever it is would still require running compiled code on Windows somehow. Cheers, Ganesh From profunctor at pm.me Wed May 6 10:48:21 2020 From: profunctor at pm.me (Marcin Szamotulski) Date: Wed, 06 May 2020 10:48:21 +0000 Subject: [Haskell-cafe] Windows Haskell CI In-Reply-To: References: <20200427125749.GB15031@extensa> <063f39587e3e404334c2412b7f4ff2eddb194612.camel@joachim-breitner.de> Message-ID: Hi, In my team at IOHK we are using `github-actions` to compile and run tests natively on Windows. We are provisioning a windows machine using, now the official installation procedure of GHC on Windows: via chocolatey. We've been using it for some time and it works quite good for us so far. Here's our github-action script: https://github.com/input-output-hk/ouroboros-network/blob/master/.github/workflows/windows.yml Cheers, Marcin Szamotulski ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Monday, May 4, 2020 8:53 PM, Ganesh Sittampalam wrote: > On 29/04/2020 23:20, Ben Franksen wrote: > > > > It doesn't help for people who want to develop on windows, but at > > > least releasing for windows is prettty painless this way. > > > > Indeed, developing on Windows is something we'd very much like to avoid. > > As another darcs developer, I'm ambivalent about it. Windows certainly > has its pain points but it's the native OS on my primary machine and > developing in that OS rather than inside a VM does make many things > simpler. But it's pretty clear no-one else wants to get too close :-) > > > But what we definitely need is to be able to run our test suite on > > Windows; and a significant part of that are a couple hundred bash > > scripts. If your approach could handle that, I'd be interested to know more. > > Given how slow bash scripts are on Windows, another strategy would be to > simply rewrite them in something else, e.g. something we can directly > interpret in Haskell. But whatever it is would still require running > compiled code on Windows somehow. > > Cheers, > > Ganesh > > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 477 bytes Desc: OpenPGP digital signature URL: From bernardobruno at gmail.com Wed May 6 10:59:01 2020 From: bernardobruno at gmail.com (Bruno Bernardo) Date: Wed, 6 May 2020 12:59:01 +0200 Subject: [Haskell-cafe] FMBC 2020: 2nd Workshop on Formal Methods for Blockchains (3rd CfP, Deadline Extension) Message-ID: <42e87b03-040e-6c6c-9878-36bc1f33c07b@gmail.com> [ Please distribute, apologies for multiple postings. ] ======================================================================== 2nd Workshop on Formal Methods for Blockchains (FMBC) 2020 - Third Call https://fmbc.gitlab.io/2020 July 19, 2020 Co-located with the 32nd International Conference on Computer-Aided Verification (CAV 2020) http://i-cav.org/2020/ *Due do the COVID-19 pandemic, the workshop is likely to be held online.* ------------------------------------------------------------- IMPORTANT DATES -------------------------------- Abstract submission: May 12, 2020 (extended) Full paper submission: May 19, 2020 (extended) Notification: June 23, 2020 (extended) Camera-ready: July 14, 2020 (extended) Conference: July 19, 2020 Deadlines are Anywhere on Earth: https://en.wikipedia.org/wiki/Anywhere_on_Earth -------------------------------- -------------------------------- TOPICS OF INTEREST -------------------------------- Blockchains are decentralized transactional ledgers that rely on cryptographic hash functions for guaranteeing the integrity of the stored data. Participants on the network reach agreement on what valid transactions are through consensus algorithms. Blockchains may also provide support for Smart Contracts. Smart Contracts are scripts of an ad-hoc programming language that are stored in the Blockchain and that run on the network. They can interact with the ledger’s data and update its state. These scripts can express the logic of possibly complex contracts between users of the Blockchain. Thus, Smart Contracts can facilitate the economic activity of Blockchain participants. With the emergence and increasing popularity of cryptocurrencies such as Bitcoin and Ethereum, it is now of utmost importance to have strong guarantees of the behavior of Blockchain software. These guarantees can be brought by using Formal Methods. Indeed, Blockchain software encompasses many topics of computer science where using Formal Methods techniques and tools are relevant: consensus algorithms to ensure the liveness and the security of the data on the chain, programming languages specifically designed to write Smart Contracts, cryptographic protocols, such as zero-knowledge proofs, used to ensure privacy, etc. This workshop is a forum to identify theoretical and practical approaches of formal methods for Blockchain technology. Topics include, but are not limited to: * Formal models of Blockchain applications or concepts * Formal methods for consensus protocols * Formal methods for Blockchain-specific cryptographic primitives or protocols * Design and implementation of Smart Contract languages * Verification of Smart Contracts -------------------------------- -------------------------------- SUBMISSION -------------------------------- Submit original manuscripts (not published or considered elsewhere) with a maximum of twelve pages (full papers), six pages (short papers), and two pages (extended abstract) describing new and emerging ideas or summarizing existing work). Each paper should include a title and the name and affiliation of each author. Authors of selected extended-abstracts are invited to give a short lightning talk. At least one author of an accepted paper is expected to present the paper at the workshop as a registered participant. Submission link: https://easychair.org/conferences/?conf=fmbc2020 The authors are encouraged to use LaTeX and the EasyChair style files: https://easychair.org/publications/for_authors -------------------------------- -------------------------------- PROCEEDINGS -------------------------------- All submissions will be peer-reviewed by at least three members of the program committee for quality and relevance. Accepted regular papers (full and short papers) will be included in the workshop proceedings, published as a volume of the OpenAccess Series in Informatics (OASIcs) by Dagstuhl. -------------------------------- -------------------------------- INVITED SPEAKER -------------------------------- Grigore Rosu, Professor at University of Illinois at Urbana-Champaign, USA and Founder of Runtime Verification http://fsl.cs.illinois.edu/index.php/Grigore_Rosu https://runtimeverification.com/ -------------------------------- -------------------------------- PROGRAM COMMITTEE -------------------------------- PC CO-CHAIRS * Bruno Bernardo (Nomadic Labs, France) (bruno at nomadic-labs.com) * Diego Marmsoler (University of Exeter, UK) (D.Marmsoler at exeter.ac.uk) PC MEMBERS * Wolfgang Ahrendt (Chalmers University of Technology, Sweden) * Lacramioara Astefanoei (Nomadic Labs, France) * Massimo Bartoletti (University of Cagliari, Italy) * Bernhard Beckert (Karlsruhe Institute of Technology, Germany) * Achim Brucker (University of Exeter, UK) * Silvia Crafa (Universita di Padova, Italy) * Zaynah Dargaye (Nomadic Labs, France) * Jérémie Decouchant (University of Luxembourg, Luxembourg) * Ansgar Fehnker (University of Twente, Netherlands) * Georges Gonthier (Inria, France) * Florian Kammueller (Middlesex University London, UK) * Maurice Herlihy (Brown University, USA) * Igor Konnov (Informal, Austria) * Andreas Lochbihler (Digital Asset, Switzerland) * Anastasia Mavridou (NASA Ames, USA) * Simão Melo de Sousa (Universidade da Beira Interior, Portugal) * Andrew Miller (University of Illinois at Urbana-Champaign, USA) * Karl Palmskog (KTH, Sweden) * Vincent Rahli (University of Birmingham, UK) * Andreas Rossberg (Dfinity Foundation, Germany) * Claudio Russo (Dfinity Foundation, USA) * César Sanchez (Imdea, Spain) * Clara Schneidewind (TU Wien, Austria) * Ilya Sergey (Yale-NUS College/NUS, Singapore) * Bas Spitters (Aarhus University/Concordium, Denmark) * Mark Staples (CSIRO Data61, Australia) * Meng Sun (Peking University, China) * Simon Thompson (University of Kent, UK) * Philip Wadler (University of Edinburgh / IOHK, UK) From berdario at gmail.com Wed May 6 11:12:38 2020 From: berdario at gmail.com (Dario Bertini) Date: Wed, 6 May 2020 12:12:38 +0100 Subject: [Haskell-cafe] Windows Haskell CI In-Reply-To: References: <20200427125749.GB15031@extensa> <063f39587e3e404334c2412b7f4ff2eddb194612.camel@joachim-breitner.de> Message-ID: AppVeyor worked pretty reliably for me, though I haven't touched it in 3 years: https://ci.appveyor.com/project/berdario/c-repl/history As you can see, a new build can complete in less than 4 minutes The configuration is here: https://github.com/berdario/jira2sheet/blob/master/appveyor.yml (it also automatically uploads built artifacts on github) Don't pay too much attention to the code, I wrote it that way to get some practice with mtl-style effects, and it might be a bit too complex for its own good :) On Wed, May 6, 2020 at 11:49 AM Marcin Szamotulski via Haskell-Cafe < haskell-cafe at haskell.org> wrote: > Hi, > > In my team at IOHK we are using `github-actions` to compile and run tests > natively on Windows. We are provisioning a windows machine using, now the > official installation procedure of GHC on Windows: via chocolatey. We've > been using it for some time and it works quite good for us so far. > > Here's our github-action script: > > https://github.com/input-output-hk/ouroboros-network/blob/master/.github/workflows/windows.yml > > Cheers, > Marcin Szamotulski > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > On Monday, May 4, 2020 8:53 PM, Ganesh Sittampalam > wrote: > > > On 29/04/2020 23:20, Ben Franksen wrote: > > > > > > > It doesn't help for people who want to develop on windows, but at > > > > least releasing for windows is prettty painless this way. > > > > > > > Indeed, developing on Windows is something we'd very much like to > avoid. > > > > > As another darcs developer, I'm ambivalent about it. Windows certainly > > has its pain points but it's the native OS on my primary machine and > > developing in that OS rather than inside a VM does make many things > > simpler. But it's pretty clear no-one else wants to get too close :-) > > > > > > But what we definitely need is to be able to run our test suite on > > > Windows; and a significant part of that are a couple hundred bash > > > scripts. If your approach could handle that, I'd be interested to know > more. > > > > > Given how slow bash scripts are on Windows, another strategy would be to > > simply rewrite them in something else, e.g. something we can directly > > interpret in Haskell. But whatever it is would still require running > > compiled code on Windows somehow. > > > > > Cheers, > > > > > Ganesh > > > > > Haskell-Cafe mailing list > > To (un)subscribe, modify options or view archives go to: > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > > Only members subscribed via the mailman list are allowed to post. > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ben.franksen at online.de Wed May 6 13:40:15 2020 From: ben.franksen at online.de (Ben Franksen) Date: Wed, 6 May 2020 15:40:15 +0200 Subject: [Haskell-cafe] Windows Haskell CI In-Reply-To: References: <20200427125749.GB15031@extensa> <063f39587e3e404334c2412b7f4ff2eddb194612.camel@joachim-breitner.de> Message-ID: Hi Everyone thanks for you input; I'll certainly take a look at your various solutions. Hi Ganesh Am 04.05.20 um 20:53 schrieb Ganesh Sittampalam: > On 29/04/2020 23:20, Ben Franksen wrote: >> Indeed, developing on Windows is something we'd very much like to avoid. > > As another darcs developer, I'm ambivalent about it. Windows certainly > has its pain points but it's the native OS on my primary machine and > developing in that OS rather than inside a VM does make many things > simpler. But it's pretty clear no-one else wants to get too close :-) Sorry, I should have been speaking only for myself. My goal is to have a way to build and run the tests on Windows without being bogged down with Windows intricacies. I think that indeed Appveyor may serve this purpose. We'll have to create a small git repo with the configuration and a small number of scripts ("batch files"?) to manage the darcs side of things, like cloning our repo(s). I know of at least on example where it was done in this way. >> But what we definitely need is to be able to run our test suite on >> Windows; and a significant part of that are a couple hundred bash >> scripts. If your approach could handle that, I'd be interested to know more. > > Given how slow bash scripts are on Windows, another strategy would be to > simply rewrite them in something else, e.g. something we can directly > interpret in Haskell. But whatever it is would still require running > compiled code on Windows somehow. You must be aware that we currently have 380 bash scripts. Rewriting them all cannot be described with the word "simply", even if such a translation were simple for a single script, which I doubt very much it is. We should probably continue to discuss this on darcs-devel. Cheers Ben From carter.schonwald at gmail.com Fri May 8 13:33:51 2020 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Fri, 8 May 2020 09:33:51 -0400 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> Message-ID: On Fri, May 8, 2020 at 9:32 AM Carter Schonwald wrote: > ben, could you please email the libraries list with this too? This seems > like a core libraries / base change rather than a ghc-the-compiler change > > On Thu, May 7, 2020 at 6:57 PM Michael Sloan wrote: > >> Thanks so much for making a proposal for this, Ben!! It's great to see >> progress here. >> >> I'm also glad that there is now a proposal process. I made a fairly >> similar proposal almost exactly 5 years ago to the libraries list - >> https://mail.haskell.org/pipermail/libraries/2015-April/025471.html - >> but without the subtlety of particular backtrace representations. Skimming >> the ensuing thread may still be informative. >> >> In particular, there is one thing I would like to highlight from that old >> proposal. I think it'd be good to have a standard way to represent a chain >> of exceptions, and build this into `catch` and `finally`. Python and Java >> both have a mechanism for this, and both refer to it as a "cause" >> exception. When an exception is thrown during exception handling, the >> exception being handled is preserved as its "cause". I find this mechanism >> to be incredibly useful in Java, it has made the underlying issue much >> clearer in many cases, and in other cases at least provides helpful >> context. I have no doubt such a mechanism would have saved me many hours >> of debugging exceptions in Haskell systems I've worked on in the past. >> >> I considered commenting about that directly on the proposal, but I figure >> this is a better place to suggest expanding the scope of the change :) . >> Totally understandable if you want to keep this proposal focused on >> stacktraces, but I think it'd be good to consider this as a potential >> future improvement. >> >> -Michael >> >> On Thu, May 7, 2020 at 3:55 PM Ben Gamari wrote: >> >>> >>> Hi everyone, >>> >>> After a nice discussion on IRC about the unfortunate state of error >>> reporting in Haskell, I felt compelled to write down some long-lingering >>> thoughts regarding backtraces on exceptions. The result is GHC proposal >>> #330 [1]. I think the approach is viable and perhaps even >>> straightforward. I have the sketch of an implementation here [2]. >>> >>> Please have a look at the proposal and leave your comments. If there is >>> consensus it is possible that we could have this done for 8.12. >>> >>> Cheers, >>> >>> - Ben >>> >>> >>> [1] https://github.com/ghc-proposals/ghc-proposals/pull/330 >>> [2] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3236 >>> _______________________________________________ >>> ghc-devs mailing list >>> ghc-devs at haskell.org >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >>> >> _______________________________________________ >> ghc-devs mailing list >> ghc-devs at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Fri May 8 15:37:36 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 8 May 2020 17:37:36 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> Message-ID: There seem to be multiple beginnings of the discussion. What is currently discussed? If someone says "exceptions" and "backtrace" in one sentence, I suspect like many times before, that again confusion of the concepts of exceptions and errors is ahead. Errors already support call stacks. Why should exceptions get them, too? Exceptions should carry information that is useful for a user, but a callstack is not useful for a user. I can imagine that it would be helpful for the user to get a stacked exception information like: Parse error on line 42, column 23 while reading file "foo/bar" while traversing directory "blabla" But since you refer to the CallStack feature of GHC, this seems not to be addressed in the proposals. On Fri, 8 May 2020, Carter Schonwald wrote: > I have no doubt such a mechanism would have saved me many hours of > debugging exceptions in Haskell systems I've worked on in the past. If you must debug exceptions, then this sounds like exceptions were abused for programming errors. Ben writes in: http://www.well-typed.com/blog/2020/04/dwarf-3/ "Unfortunately, the untyped nature of Haskell exceptions complicates the migration path for existing code." Actually, it only proves again, that it was wrong from the beginning to hide information about potential exceptions in the IO monad instead of making them explicit via ExceptionalT, ExceptT or the like. From mail at nh2.me Fri May 8 17:27:35 2020 From: mail at nh2.me (=?UTF-8?Q?Niklas_Hamb=c3=bcchen?=) Date: Fri, 8 May 2020 19:27:35 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> Message-ID: <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> On 5/8/20 5:37 PM, Henning Thielemann wrote: > I can imagine that it would be helpful for the user to get a stacked exception information like: >    Parse error on line 42, column 23 >    while reading file "foo/bar" >    while traversing directory "blabla" That seems to be rather specific use case. It'd be a cool feature but I'm not aware of any programming language following that interpretation so far. I personally would be happy to be able to get the same type of stack trace for exceptions as in other programming langues (and as the proposal suggests). > If you must debug exceptions, then this sounds like exceptions were abused for programming errors. I'd be pretty happy to be able to debug them better; no matter if they were "abused" for anything or not, I must still debug them in practice. Given that they traverse program flow invisibly (e.g. not lexically, like return values) and can become visible in different places than they arose, having a call stack to debug their creation would be useful. > a callstack is not useful for a user. Call stacks have been very useful to me as a user of non-Haskell tools so far, because they are excellent for attaching to bug reports and usually led to developers fixing my problems faster. From lemming at henning-thielemann.de Fri May 8 17:32:54 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 8 May 2020 19:32:54 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> Message-ID: On Fri, 8 May 2020, Niklas Hambüchen wrote: > On 5/8/20 5:37 PM, Henning Thielemann wrote: > >> a callstack is not useful for a user. > > Call stacks have been very useful to me as a user of non-Haskell tools > so far, because they are excellent for attaching to bug reports and > usually led to developers fixing my problems faster. This confirms that they are not for you, but you only forward them to the developer. Can someone please give me examples where current state lacks and how they are addressed by the proposal(s)? From mail at nh2.me Fri May 8 17:47:03 2020 From: mail at nh2.me (=?UTF-8?Q?Niklas_Hamb=c3=bcchen?=) Date: Fri, 8 May 2020 19:47:03 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> Message-ID: <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> On 5/8/20 7:32 PM, Henning Thielemann wrote: > This confirms that they are not for you, but you only forward them to the developer. Yes, stack traces are in general for developers. > Can someone please give me examples where current state lacks * Currently stack traces are not printed, so users cannot forward them to the developer, even if both the users and the developers would like that. * Developers cannot easily produce stack traces do debug unintended exceptions. From lemming at henning-thielemann.de Fri May 8 17:52:13 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 8 May 2020 19:52:13 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> Message-ID: On Fri, 8 May 2020, Niklas Hambüchen wrote: > On 5/8/20 7:32 PM, Henning Thielemann wrote: > >> Can someone please give me examples where current state lacks > > * Currently stack traces are not printed, so users cannot forward them > to the developer, even if both the users and the developers would like > that. We are talking about the HasCallStack stack traces, yes? How is their emission addressed by extending exceptions with stack traces? > * Developers cannot easily produce stack traces do debug unintended > exceptions. What are "unintended exceptions"? What is an example of an "unintended exception"? From mail at nh2.me Fri May 8 18:00:29 2020 From: mail at nh2.me (=?UTF-8?Q?Niklas_Hamb=c3=bcchen?=) Date: Fri, 8 May 2020 20:00:29 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> Message-ID: <517044fa-4fb2-cde6-3a8c-b1013f7b06f0@nh2.me> On 5/8/20 7:52 PM, Henning Thielemann wrote: > We are talking about the HasCallStack stack traces, yes? > How is their emission addressed by extending exceptions with stack traces? The way I understand the proposal, we may be equally talking about DWARF or profiling cost-center based stack traces. >From a debugging perspective, I guess the developer does not care so much about which implementation is used, as long as the trace points out the code path that led to the creation of the exception. > What are "unintended exceptions"? > What is an example of an "unintended exception"? A recent example from my production server: hPutBuf: resource vanished (Broken pipe) From ben at well-typed.com Fri May 8 18:03:41 2020 From: ben at well-typed.com (Ben Gamari) Date: Fri, 08 May 2020 14:03:41 -0400 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> Message-ID: <87mu6i1eyw.fsf@smart-cactus.org> Henning Thielemann writes: > On Fri, 8 May 2020, Niklas Hambüchen wrote: > >> On 5/8/20 5:37 PM, Henning Thielemann wrote: >> >>> a callstack is not useful for a user. >> >> Call stacks have been very useful to me as a user of non-Haskell tools >> so far, because they are excellent for attaching to bug reports and >> usually led to developers fixing my problems faster. > > This confirms that they are not for you, but you only forward them to the > developer. > > > Can someone please give me examples where current state lacks and how they > are addressed by the proposal(s)? We can debate whether partial functions like `fromJust` should exist; however, the fact of the matter is that they do exist and they are used. Furthermore, even `base`'s own IO library (e.g. `openFile`) uses synchronous exceptions to report errors. This becomes particularly painful when building large systems: Even if I am careful to avoid such functions in my own code, as my dependency footprint grows it becomes more likely that some transitive dependency will expose a partial interface (perhaps even without my knowledge). This is a problem that industrial users are all too familiar with. Perhaps this helps to shed some light on the motivation? Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From ben at well-typed.com Fri May 8 18:18:38 2020 From: ben at well-typed.com (Ben Gamari) Date: Fri, 08 May 2020 14:18:38 -0400 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> Message-ID: <87k11m1e9z.fsf@smart-cactus.org> Henning Thielemann writes: > On Fri, 8 May 2020, Niklas Hambüchen wrote: > >> On 5/8/20 7:32 PM, Henning Thielemann wrote: >> >>> Can someone please give me examples where current state lacks >> >> * Currently stack traces are not printed, so users cannot forward them >> to the developer, even if both the users and the developers would like >> that. > > We are talking about the HasCallStack stack traces, yes? > How is their emission addressed by extending exceptions with stack > traces? HasCallStack stack traces are one type of backtrace that the proposal supports. However, it's not the only (nor is it even the most useful sort, in my opinion). Other mechanisms include cost center stacks from the cost-center profiler and native stack unwinding. > >> * Developers cannot easily produce stack traces do debug unintended >> exceptions. > > What are "unintended exceptions"? > What is an example of an "unintended exception"? For instance, * Somewhere deep in my code a colleague used `fromJust` due to a miscommunicated invariant * Somewhere in my system a `writeFile "tmp" $ repeat 'a'` failed due to filling the disk * Somewhere in my system I have a partial pattern match in a module which was compiled without -Wall * Somewhere in my system I `div` by zero due to lack of input validation * I use a record selector on a sum. * A logic error results in an assertion failure deep in my program, but it's unclear which path my program took to arrive at the assertion This list could go on and on... Currently the proposal does not cover asynchronous exceptions but it wouldn't be particularly hard to extend it in this direction. This would allow far better reporting of heap/stack overflows and MVar deadlocks (which are particularly hard to debug at the moment). Cheers, - Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From compl.yue at gmail.com Sat May 9 06:35:17 2020 From: compl.yue at gmail.com (Compl Yue) Date: Sat, 9 May 2020 14:35:17 +0800 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <87k11m1e9z.fsf@smart-cactus.org> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> <87k11m1e9z.fsf@smart-cactus.org> Message-ID: This reminds me a joke to put it in a humorous way: > A software QA engineer walks into a bar. He orders a beer. Orders 0 beers. Orders 99999999999 beers. Orders a lizard. Orders -1 beers. > First real customer walks in and asks where the bathroom is. The bar bursts into flames, killing everyone. LOL, Compl > On 2020-05-09, at 02:18, Ben Gamari wrote: > > Henning Thielemann writes: > >> On Fri, 8 May 2020, Niklas Hambüchen wrote: >> >>> On 5/8/20 7:32 PM, Henning Thielemann wrote: >>> >>>> Can someone please give me examples where current state lacks >>> >>> * Currently stack traces are not printed, so users cannot forward them >>> to the developer, even if both the users and the developers would like >>> that. >> >> We are talking about the HasCallStack stack traces, yes? >> How is their emission addressed by extending exceptions with stack >> traces? > > HasCallStack stack traces are one type of backtrace that the proposal > supports. However, it's not the only (nor is it even the most useful > sort, in my opinion). > > Other mechanisms include cost center stacks from the cost-center > profiler and native stack unwinding. > >> >>> * Developers cannot easily produce stack traces do debug unintended >>> exceptions. >> >> What are "unintended exceptions"? >> What is an example of an "unintended exception"? > > For instance, > > * Somewhere deep in my code a colleague used `fromJust` due to a > miscommunicated invariant > > * Somewhere in my system a `writeFile "tmp" $ repeat 'a'` failed due to > filling the disk > > * Somewhere in my system I have a partial pattern match in a module > which was compiled without -Wall > > * Somewhere in my system I `div` by zero due to lack of input > validation > > * I use a record selector on a sum. > > * A logic error results in an assertion failure deep in my program, but > it's unclear which path my program took to arrive at the assertion > > This list could go on and on... > > Currently the proposal does not cover asynchronous exceptions but it > wouldn't be particularly hard to extend it in this direction. This would > allow far better reporting of heap/stack overflows and MVar deadlocks > (which are particularly hard to debug at the moment). > > Cheers, > > - Ben > _______________________________________________ > ghc-devs mailing list > ghc-devs at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at gmail.com Sat May 9 08:15:41 2020 From: compl.yue at gmail.com (Compl Yue) Date: Sat, 9 May 2020 16:15:41 +0800 Subject: [Haskell-cafe] network's example echo server seems leaking socket on error binding Message-ID: Hi folks, I just filed an issue https://github.com/haskell/network/issues/447 with the network package, I'd like to post here too in seeking your wisedom at the same time. In top-level doc, the minimal example echo server uses Control.Exception.bracket like this: E.bracket (open addr) close loop where resolve = do let hints = defaultHints { addrFlags = [AI_PASSIVE] , addrSocketType = Stream } head <$> getAddrInfo (Just hints) mhost (Just port) open addr = do sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) setSocketOption sock ReuseAddr 1 withFdSocket sock setCloseOnExecIfNeeded bind sock $ addrAddress addr listen sock 1024 return sock loop sock = forever $ do (conn, _peer) <- accept sock void $ forkFinally (server conn) (const $ gracefulClose conn 5000) I happened to copy the configuration with another machine's IP address to run on my dev machine, then of course it failed binding to the IP, but in this case I suspect sock above is leaked without close, as open failed at all, so sock is not given to bracket for it to do the cleanup. Is my suspicion correct ? Or I missed something that the example actually won't leak on binding errors ? Best regards, Compl -------------- next part -------------- An HTML attachment was scrubbed... URL: From merijn at inconsistent.nl Sat May 9 09:45:47 2020 From: merijn at inconsistent.nl (Merijn Verstraaten) Date: Sat, 9 May 2020 11:45:47 +0200 Subject: [Haskell-cafe] network's example echo server seems leaking socket on error binding In-Reply-To: References: Message-ID: > > On 9 May 2020, at 10:15, Compl Yue wrote: > > Is my suspicion correct ? Or I missed something that the example actually won't leak on binding errors ? You are correct, the allocation in "open" must be atomic (so either fully succeed or allocate nothing), else it will leak resources. The open here needs further bracketing internally to properly/safely handle this case. One solution would be to use bracketOnError (which only runs the cleanup on exception in the body), creating the socket in the "alloc" of bracketOnError, then do the binding inside the body of bracketOnError and returning the bound socket. So open addr = bracketOnError (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)) close $ \sock -> do setSocketOption sock ReuseAddr 1 withFdSocket sock setCloseOnExecIfNeeded bind sock $ addrAddress addr listen sock 1024 return sock Alternatively this can be addressed by Acquire from the resourcet package. Cheers, Merijn -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From lemming at henning-thielemann.de Sat May 9 09:53:44 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 9 May 2020 11:53:44 +0200 (CEST) Subject: [Haskell-cafe] network's example echo server seems leaking socket on error binding In-Reply-To: References: Message-ID: On Sat, 9 May 2020, Compl Yue wrote: > In top-level doc, the minimal example echo server uses Control.Exception.bracket like this: > > E.bracket (open addr) close loop > where > resolve = do > let hints = defaultHints { > addrFlags = [AI_PASSIVE] > , addrSocketType = Stream > } > head <$> getAddrInfo (Just hints) mhost (Just port) > open addr = do > sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr) > setSocketOption sock ReuseAddr 1 > withFdSocket sock setCloseOnExecIfNeeded > bind sock $ addrAddress addr > listen sock 1024 > return sock > loop sock = forever $ do > (conn, _peer) <- accept sock > void $ forkFinally (server conn) (const $ gracefulClose conn 5000) > > I happened to copy the configuration with another machine's IP address to run on my dev machine, then of course > it failed binding to the IP, but in this case I suspect sock above is leaked without close, as open failed at > all, so sock is not given to bracket for it to do the cleanup. I think you are right. If 'bind' throws an exception then 'close' will not be called. You might move the block from 'setSocketOption' to 'listen' into 'loop' before 'forever'. From mgajda at mimuw.edu.pl Sat May 9 12:23:57 2020 From: mgajda at mimuw.edu.pl (Michal J Gajda) Date: Sat, 9 May 2020 14:23:57 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information Message-ID: Ben, I agree with you that is a great idea! I can add a few more real world examples: * we get exception from a foreign library that we bound, * we get an exception from a platform (I believe Windows supports throwing exceptions to programs), * user presses CTRL-C and we want to know where our program hanged. * we get infamous <>, because in theory nobody wants non-terminating programs, but in practice everybody gets them sometimes. I also use `ExceptT`, `EitherT` for processing large sets of data, because that allows me to contain the errors efficiently. However from time to time, I get an error to blow up **and I cannot even locate which library was guilty**. It would be nice to extract them automatically and put them into error database before they are prioritized. -- Cheers Michał From ietf-dane at dukhovni.org Sun May 10 04:27:23 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 10 May 2020 00:27:23 -0400 Subject: [Haskell-cafe] Coercing newtype-wrapped monad transformers? Message-ID: <20200510042723.GC76674@straasha.imrryr.org> The code sample below my signature wraps RWS.CPS in a newtype, with a view to presenting a more constrained interface with specific functions that internall use the underlying RWST features. It is straightforward to construct the appropriate variants of "ask", "get", "put", "tell", ... via appropriate applications of the FooT constructor and accessor, but I expected to be able to use "coerce", along the lines of: ask :: Monad m => RWST r w s m r ask = coerce M.ask but that fails with: foo.hs:34:7: error: • Couldn't match representation of type ‘m0’ with that of ‘m’ arising from a use of ‘coerce’ ‘m’ is a rigid type variable bound by the type signature for: ask :: forall (m :: * -> *) r w s. Monad m => FooT r w s m r at foo.hs:21:1-34 • In the expression: coerce M.ask In an equation for ‘ask’: ask = coerce M.ask • Relevant bindings include ask :: FooT r w s m r (bound at foo.hs:34:1) Somehow between the various constraints and quantifiers in play, coerce is unable to do what I expected. Should it have worked? If had worked, would the effect have been in fact any different (more efficient?) than what I get with the explicit applications of the constructor and accessor? -- Viktor. {-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleInstances, MultiParamTypeClasses, StandaloneDeriving #-} import Control.Monad.Trans.Class import qualified Control.Monad.Trans.RWS.CPS as M newtype FooT r w s m a = FooT { unFooT :: M.RWST r w s m a } deriving instance (Functor m) => Functor (FooT r w s m) deriving instance (Monad m) => Applicative (FooT r w s m) deriving instance (Monad m) => Monad (FooT r w s m) deriving instance MonadTrans (FooT r w s) runFooT :: (Monoid w, Monad m) => FooT r w s m a -> r -> s -> m (a, s, w) execFooT :: (Monoid w, Monad m) => FooT r w s m a -> r -> s -> m (s, w) evalFooT :: (Monoid w, Monad m) => FooT r w s m a -> r -> s -> m (a, w) ask :: (Monad m) => FooT r w s m r asks :: (Monad m) => (r -> a) -> FooT r w s m a get :: (Monad m) => FooT r w s m s gets :: (Monad m) => (s -> a) -> FooT r w s m a modify :: (Monad m) => (s -> s) -> FooT r w s m () pass :: (Monoid w, Monoid w', Monad m) => FooT r w' s m (a, w' -> w) -> FooT r w s m a put :: (Monad m) => s -> FooT r w s m () tell :: (Monoid w, Monad m) => w -> FooT r w s m () runFooT = M.runRWST . unFooT evalFooT = M.evalRWST . unFooT execFooT = M.execRWST . unFooT ask = FooT $ M.ask asks = FooT . M.asks get = FooT $ M.get gets = FooT . M.gets modify = FooT . M.modify pass = FooT . M.pass . unFooT put = FooT . M.put tell = FooT . M.tell main :: IO () main = runFooT mfoo "read me" "set me" >>= print where mfoo = do ask >>= modify . (. (" or " ++)) . (++) tell "Hello" pass $ do tell "World!" pure (42, (' ':)) From fa-ml at ariis.it Sun May 10 10:20:14 2020 From: fa-ml at ariis.it (Francesco Ariis) Date: Sun, 10 May 2020 12:20:14 +0200 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: References: Message-ID: <20200510102014.GA4570@extensa> Il 25 aprile 2020 alle 11:22 José Pedro Magalhães ha scritto: > I honestly don't want this to sound like a rant. I genuinely would like > to understand why this multi-step, multi-tool, multi-website process was > introduced, how it is superior to a single installer, and whether this is > really the process we want newcomers to the language have to follow. A data point from a user (OS: Win10) on freenode/#haskell-it today. Shared with permission, translated by me: - he asked: «Hello. To Windows users, can you link the installer to me? It disappeared from the site, now I need to install Chocolatey and to be honest I would prefer not to». I redirected him to the page mentioned here [1] by Ben Gamari and asked why Chocolatey was not an option for him. Reply: «I don't want to use a third party tool, Chocolatey immediately asks me to register to its newsletter... why? Those things are very annoying, I'd rather install Haskell on an RPi and use it via ssh 😅»; - once the download from [1] was over: «I have downloaded it (400Mb) but I cannot extract it and I don't know what to do with it, it's a .tar.lz file». Indeed after a cursory search, it seems a common (on Windows) open-source extracting tool like 7-zip does not natively support the format [2]. Not having used Windows in 10 years I suggested to try WinZip -- stupid idea, as it does not support ".tar.lz" either and it is proprietary nagware; - I then directed him to the Stack Win64 installer [3]. Feedback: «Microsoft Defender blocks it! 😂»; - after this, the user created an Ubuntu VM and installed Haskell via "apt-get install haskell-platform". The installation took a few minutes, he seemed satisfied with it. [1] https://mail.haskell.org/pipermail/haskell-cafe/2020-April/132150.html [2] https://sourceforge.net/p/sevenzip/discussion/45798/thread/9e77409b/?limit=25 [3] https://get.haskellstack.org/stable/windows-x86_64-installer.exe From adam at ahri.net Sun May 10 12:28:02 2020 From: adam at ahri.net (Adam Piper) Date: Sun, 10 May 2020 13:28:02 +0100 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: <20200510102014.GA4570@extensa> References: <20200510102014.GA4570@extensa> Message-ID: That's a pretty awful experience, I'm quite surprised this user followed through without just giving up. On Sun, 10 May 2020 at 11:20, Francesco Ariis wrote: > Il 25 aprile 2020 alle 11:22 José Pedro Magalhães ha scritto: > > I honestly don't want this to sound like a rant. I genuinely would like > > to understand why this multi-step, multi-tool, multi-website process was > > introduced, how it is superior to a single installer, and whether this is > > really the process we want newcomers to the language have to follow. > > A data point from a user (OS: Win10) on freenode/#haskell-it today. Shared > with permission, translated by me: > > - he asked: «Hello. To Windows users, can you link the installer to me? > It disappeared from the site, now I need to install Chocolatey and to be > honest I would prefer not to». > I redirected him to the page mentioned here [1] by Ben Gamari and asked > why Chocolatey was not an option for him. > Reply: «I don't want to use a third party tool, Chocolatey immediately > asks me to register to its newsletter... why? Those things are very > annoying, I'd rather install Haskell on an RPi and use it via ssh 😅»; > > - once the download from [1] was over: > «I have downloaded it (400Mb) but I cannot extract it and I don't know > what to do with it, it's a .tar.lz file». > Indeed after a cursory search, it seems a common (on Windows) open-source > extracting tool like 7-zip does not natively support the format [2]. > Not having used Windows in 10 years I suggested to try WinZip -- stupid > idea, as it does not support ".tar.lz" either and it is proprietary > nagware; > > - I then directed him to the Stack Win64 installer [3]. Feedback: > «Microsoft Defender blocks it! 😂»; > > - after this, the user created an Ubuntu VM and installed Haskell via > "apt-get install haskell-platform". The installation took a few minutes, > he seemed satisfied with it. > > > [1] https://mail.haskell.org/pipermail/haskell-cafe/2020-April/132150.html > [2] > https://sourceforge.net/p/sevenzip/discussion/45798/thread/9e77409b/?limit=25 > [3] https://get.haskellstack.org/stable/windows-x86_64-installer.exe > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From irfon at ambienautica.com Sun May 10 14:25:09 2020 From: irfon at ambienautica.com (Irfon-Kim Ahmad) Date: Sun, 10 May 2020 10:25:09 -0400 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: <20200510102014.GA4570@extensa> References: <20200510102014.GA4570@extensa> Message-ID: Yes, you need to know several magic things to go this route. The first is to have that link that Ben Gamari provided in the first place, which is not an obvious thing at all. The second is to know about compression formats that nobody uses on Windows. The .tar.lz file is much smaller can be decoded on Windows using lzip. lzip is available for windows as a 32-bit command-line utility from here: https://www.nongnu.org/lzip/ You need to unzip the file, copy the binaries to somewhere handy (probably a folder you create in c:\Program Files (x86) ), and then add that folder to the path. Then you need to go to the command line and use lzip -d {filename} to decompress the file. This leaves you with a .tar file, which Windows also cannot handle. Installing 7zip makes that extractable, however. You can, however, reduce the complexity of the process at the expense of bandwidth (which most people have copious amounts of these days) by downloading the .tar.xz version. Windows still can't handle this natively, but 7zip can handle both the .xz and .tar decompressions using a single program. The third thing you need to know is that: ghc-8.10.1-windows-extra-src.tar.lz (or .xz) ...which is the only thing in there with "Windows" in the name, is not, in fact, the one you want. Or at least, not that I can tell. It appears to be a bunch of extra tools required to build the source code on Windows. There's a lot in it, so I didn't explore it fully. Also, within the .lz is a bunch of .xz files, but fortunately 7zip can handle those. In any case, the file you actually want is the cryptically-named: ghc-8.10.1-x86_64-unknown-mingw32.tar.lz ...because of course "unknown" in this case means Windows, I guess? Decompressing that, untarring the result, moving the resulting folder to your 'c:\Program Files' folder, and adding the bin subfolder to your path does indeed get you a working ghc and ghci -- from the command line. It doesn't include the GUI versions that I can discern. Nonetheless, this is still probably the easiest current method of installing it. It's not actually hard to do, it just requires you to know several non-obvious things that a new user probably won't know. I'm honestly baffled by the use of .tar.lz or .tar.xz for distributing Windows software. Just using .zip would guarantee that anyone can decompress it without having to install any tools -- Windows supports .zip files natively. In any case, since it doesn't appear to be obviously documented anywhere, the steps to go this route are: 1. Download and install 7zip from here: https://www.7-zip.org/download.html 2. Navigate to the latest version's folder from here: https://downloads.haskell.org/ghc/ 3. Download ghc-[latest version]-x86_64-unknown-mingw32.tar.xz 4. Right-click it, choose 7zip, and choose Extract to Here 5. Right-click the resulting .tar file, and choose Extract to [folder named after file] 6. In that folder, you should find a folder named ghc-[version]. Copy that to 'C:\Program Files'. 7. In Control Panel, search for "Environment Variables", and click "Edit the System Environment Variables" or "Edit the Environment Variables for your Account" depending on whether you wish other users to be able to use the software. 8. Click "Environment Variables". 9. Scroll to "Path" under either your username or 'System Variables' [see note above] and click Edit. 10. Click "New" and add the 'bin' subfolder of the folder you copied (ex. C:\Program Files\ghc-8.10.1\bin) 11. It should now be installed. To test it, open a command prompt of your choice and type "ghci" or "ghc". On 2020-05-10 6:20 a.m., Francesco Ariis wrote: > Il 25 aprile 2020 alle 11:22 José Pedro Magalhães ha scritto: >> I honestly don't want this to sound like a rant. I genuinely would like >> to understand why this multi-step, multi-tool, multi-website process was >> introduced, how it is superior to a single installer, and whether this is >> really the process we want newcomers to the language have to follow. > A data point from a user (OS: Win10) on freenode/#haskell-it today. Shared > with permission, translated by me: > > - he asked: «Hello. To Windows users, can you link the installer to me? > It disappeared from the site, now I need to install Chocolatey and to be > honest I would prefer not to». > I redirected him to the page mentioned here [1] by Ben Gamari and asked > why Chocolatey was not an option for him. > Reply: «I don't want to use a third party tool, Chocolatey immediately > asks me to register to its newsletter... why? Those things are very > annoying, I'd rather install Haskell on an RPi and use it via ssh 😅»; > > - once the download from [1] was over: > «I have downloaded it (400Mb) but I cannot extract it and I don't know > what to do with it, it's a .tar.lz file». > Indeed after a cursory search, it seems a common (on Windows) open-source > extracting tool like 7-zip does not natively support the format [2]. > Not having used Windows in 10 years I suggested to try WinZip -- stupid > idea, as it does not support ".tar.lz" either and it is proprietary > nagware; > > - I then directed him to the Stack Win64 installer [3]. Feedback: > «Microsoft Defender blocks it! 😂»; > > - after this, the user created an Ubuntu VM and installed Haskell via > "apt-get install haskell-platform". The installation took a few minutes, > he seemed satisfied with it. > > > [1] https://mail.haskell.org/pipermail/haskell-cafe/2020-April/132150.html > [2] https://sourceforge.net/p/sevenzip/discussion/45798/thread/9e77409b/?limit=25 > [3] https://get.haskellstack.org/stable/windows-x86_64-installer.exe > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. From viercc at gmail.com Sun May 10 14:28:43 2020 From: viercc at gmail.com (=?UTF-8?B?5a6u6YeM5rS45Y+4?=) Date: Sun, 10 May 2020 23:28:43 +0900 Subject: [Haskell-cafe] Coercing newtype-wrapped monad transformers? In-Reply-To: <20200510042723.GC76674@straasha.imrryr.org> References: <20200510042723.GC76674@straasha.imrryr.org> Message-ID: Hello, I think I can answer. In the failing code, the type of "M.ask" have no constraint, so it gets the type "(Monad m0) => M.RWST r0 w0 s0 m0 r0", where "r0, w0, s0, m0" are some unconstrained types. To resolve "Coercible (M.RWST r0 w0 s0 m0 r0) (FooT r w s m r)", you can You want "m0" be equal to "m", but it can't be inferred. > ask :: Monad m => RWST r w s m r -- You mean FooT? > ask = coerce M.ask This error can be fixed by specifying concrete type you want. {-# LANGUAGE ScopedTypeVariables #-} ask :: forall m r w s. Monad m => FooT r w s m r ask = coerce (M.ask :: M.RWST r w s m r) Or, you can make a specialized coerce function: {-# LANGUAGE PolyKinds #-} coerce5 :: Coercible f g => f r w s m a -> g r w s m a coerce5 = coerce ask :: Monad m => FooT r w s m r ask = coerce5 M.ask -- /* Koji Miyazato */ From hadruki at protonmail.com Sun May 10 14:44:10 2020 From: hadruki at protonmail.com (Hadruki) Date: Sun, 10 May 2020 14:44:10 +0000 Subject: [Haskell-cafe] Problem with Model entity (persistent-template) Message-ID: Hi I have a project built around servant + persistent(-postgresql) + esqueleto (and many other libraries). I recently upgraded it to newer versions of GHC and my dependencies and I'm running into a problem which I don't fully understand. ``` • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘==’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> ghc-prim-0.5.3:GHC.Prim.Int# -> Bool’ to type ‘Key ActivationCode -> Key ActivationCode -> Bool’ • When deriving the instance for (Eq (Key ActivationCode)) + other similar ``` (full trace + Model.hs below) I get these errors on all my model entities. First of all I don't really understand the error message and I don't understand why I am getting it. I am using these entities (and their key) in esqueleto database operations: ``` findActivationCodeById :: ActivationCodeId -> IO (Entity ActivationCode) ``` I don't get the error if I build with `stack build --fast` (at least the Model.hs builds). I've tried to reproduce this on a smaller project with nothing but this Model file however it compiles there. Additionally even if I remove the `deriving Eq` it doesn't change the error (it's still deriving Eq, Ord, ..). Could anyone give me some hints where I should start looking? Is it due to a language extension? In my (generated) cabal ``` default-extensions: TypeOperators OverloadedStrings DeriveGeneric RecordWildCards DuplicateRecordFields StrictData ``` Thanks! Model.hs (trimmed down to just one entity) {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleInstances #-} -- allow json in data model module Prolix.Model.Model where import qualified Data.Aeson as Aeson import qualified Data.Fixed as Fixed import Data.Text (Text) import Data.Time import Data.Typeable (Typeable) import Database.Persist.Postgresql import Database.Persist.TH import GHC.Generics share [ mkPersist sqlSettings , mkDeleteCascade sqlSettings , mkMigrate "migrateAll" ] [persistLowerCase| ActivationCode json productCode Int sql=accd_product_code code Text sql=accd_code provider Text sql=accd_provider exported Bool sql=accd_exported exportedOn UTCTime Maybe sql=accd_exported_on createdOn UTCTime sql=accd_created_on default=now() modifiedOn UTCTime sql=accd_modified_on default=now() UniqueActivationCode code provider deriving Eq Ord Show Generic |] Full trace [ 54 of 155] Compiling Prolix.Model.Model ( src/Prolix/Model/Model.hs, .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build/Prolix/Model/Model.o ) [Optimisation flags changed] /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘==’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> ghc-prim-0.5.3:GHC.Prim.Int# -> Bool’ to type ‘Key ActivationCode -> Key ActivationCode -> Bool’ • When deriving the instance for (Eq (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘compare’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> ghc-prim-0.5.3:GHC.Prim.Int# -> Ordering’ to type ‘Key ActivationCode -> Key ActivationCode -> Ordering’ • When deriving the instance for (Ord (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘path-pieces-0.2.1:Web.PathPieces.toPathPiece’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> Text’ to type ‘Key ActivationCode -> Text’ • When deriving the instance for (path-pieces-0.2.1:Web.PathPieces.PathPiece (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘Web.Internal.HttpApiData.toUrlPiece’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> Text’ to type ‘Key ActivationCode -> Text’ • When deriving the instance for (Web.Internal.HttpApiData.ToHttpApiData (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • No instance for (Web.Internal.HttpApiData.FromHttpApiData ghc-prim-0.5.3:GHC.Prim.Int#) arising from the 'deriving' clause of a data type declaration Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself • When deriving the instance for (Web.Internal.HttpApiData.FromHttpApiData (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘toPersistValue’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> PersistValue’ to type ‘Key ActivationCode -> PersistValue’ • When deriving the instance for (PersistField (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘sqlType’ from type ‘Data.Proxy.Proxy ghc-prim-0.5.3:GHC.Prim.Int# -> SqlType’ to type ‘Data.Proxy.Proxy (Key ActivationCode) -> SqlType’ • When deriving the instance for (PersistFieldSql (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘Aeson.toJSON’ from type ‘ghc-prim-0.5.3:GHC.Prim.Int# -> Aeson.Value’ to type ‘Key ActivationCode -> Aeson.Value’ • When deriving the instance for (Aeson.ToJSON (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... /src/hadruki/prolix/src/Prolix/Model/Model.hs:35:1: error: • No instance for (Aeson.FromJSON ghc-prim-0.5.3:GHC.Prim.Int#) arising from the 'deriving' clause of a data type declaration Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself • When deriving the instance for (Aeson.FromJSON (Key ActivationCode)) | 35 | share [ mkPersist sqlSettings | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Sun May 10 19:20:56 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 10 May 2020 15:20:56 -0400 Subject: [Haskell-cafe] Coercing newtype-wrapped monad transformers? In-Reply-To: References: <20200510042723.GC76674@straasha.imrryr.org> Message-ID: <20200510192056.GF76674@straasha.imrryr.org> On Sun, May 10, 2020 at 11:28:43PM +0900, 宮里洸司 wrote: > Hello, I think I can answer. Many thanks, you answer was perfect. > In the failing code, the type of "M.ask" have no constraint, so it gets the type > "(Monad m0) => M.RWST r0 w0 s0 m0 r0", where "r0, w0, s0, m0" are some > unconstrained types. > > To resolve "Coercible (M.RWST r0 w0 s0 m0 r0) (FooT r w s m r)", you can > > You want "m0" be equal to "m", but it can't be inferred. > > > ask :: Monad m => RWST r w s m r -- You mean FooT? [yes] > > ask = coerce M.ask > > This error can be fixed by specifying concrete type you want. > > {-# LANGUAGE ScopedTypeVariables #-} > ask :: forall m r w s. Monad m => FooT r w s m r > ask = coerce (M.ask :: M.RWST r w s m r) I ended going with the below, with my module exporting only a higher-level interface that uses RWST internally, but exports a more abstract monad, hiding the implementation details. {-# LANGUAGE ScopedTypeVariables #-} import qualified Control.Monad.Trans.RWS.CPS as RWS import Data.Coerce (coerce) newtype RWST r w s m a = RWST (RWS.RWST r w s m a) deriving instance MonadTrans (RWST r w s) deriving instance (Monad m) => Functor (RWST r w s m) deriving instance (Monad m) => Applicative (RWST r w s m) deriving instance (Monad m) => Monad (RWST r w s m) type EvalM f r w s m a = (Monoid w, Monad m) => f r w s m a -> r -> s -> m (a, w) evalRWST :: forall r w s m a. EvalM RWST r w s m a evalRWST = coerce (RWS.evalRWST :: EvalM RWS.RWST r w s m a) type AskM f r w s m = Monad m => f r w s m r ask :: forall r w s m. AskM RWST r w s m ask = coerce (RWS.ask :: AskM RWS.RWST r w s m) type GetM f r w s m = Monad m => f r w s m s get :: forall r w s m. GetM RWST r w s m get = coerce (RWS.get :: GetM RWS.RWST r w s m) type PutM f r w s m = (Monad m) => s -> f r w s m () put :: forall r w s m. PutM RWST r w s m put = coerce (RWS.put :: PutM RWS.RWST r w s m) type TellM f r w s m = (Monoid w, Monad m) => w -> f r w s m () tell :: forall r w s m. TellM RWST r w s m tell = coerce (RWS.tell :: TellM RWS.RWST r w s m) type GetsM f r w s m a = Monad m => (s -> a) -> f r w s m a gets :: forall r w s m a. GetsM RWST r w s m a gets = coerce (RWS.gets :: GetsM RWS.RWST r w s m a) type LocalM f r w s m a = Monad m => (r -> r) -> f r w s m a -> f r w s m a local :: forall r w s m a. LocalM RWST r w s m a local = coerce (RWS.local :: LocalM RWS.RWST r w s m a) type PassM f r w s m a w' = (Monoid w, Monoid w', Monad m) => f r w' s m (a, w' -> w) -> f r w s m a pass :: forall r w s m a w'. PassM RWST r w s m a w' pass = coerce (RWS.pass :: PassM RWS.RWST r w s m a w') ... etc. if/as more are needed later ... -- Viktor. From doug at cs.dartmouth.edu Sun May 10 19:41:29 2020 From: doug at cs.dartmouth.edu (Doug McIlroy) Date: Sun, 10 May 2020 15:41:29 -0400 Subject: [Haskell-cafe] Decorating exceptions with backtrace information Message-ID: <202005101941.04AJfTJ8050033@tahoe.cs.Dartmouth.EDU> > in theory nobody wants non-terminating programs, but in practice > everybody gets them sometimes Without impugning the basic point, I am amused by the premise. What hooked me on Haskell was the clean way in which the nonterminating programs I did want to write could be expressed in terms of lazy lists. Doug From ietf-dane at dukhovni.org Mon May 11 00:55:56 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 10 May 2020 20:55:56 -0400 Subject: [Haskell-cafe] Missing mil classes for RWST.CPS (was: Coercing newtype-wrapped monad transformers?) In-Reply-To: <20200510192056.GF76674@straasha.imrryr.org> References: <20200510042723.GC76674@straasha.imrryr.org> <20200510192056.GF76674@straasha.imrryr.org> Message-ID: > On May 10, 2020, at 3:20 PM, Viktor Dukhovni wrote: > > I ended going with the below, with my module exporting only a > higher-level interface that uses RWST internally, but exports > a more abstract monad, hiding the implementation details. > > {-# LANGUAGE ScopedTypeVariables #-} > import qualified Control.Monad.Trans.RWS.CPS as RWS > import Data.Coerce (coerce) > > newtype RWST r w s m a = RWST (RWS.RWST r w s m a) > deriving instance MonadTrans (RWST r w s) > deriving instance (Monad m) => Functor (RWST r w s m) > deriving instance (Monad m) => Applicative (RWST r w s m) > deriving instance (Monad m) => Monad (RWST r w s m) > > type EvalM f r w s m a = (Monoid w, Monad m) => f r w s m a -> r -> s -> m (a, w) > evalRWST :: forall r w s m a. EvalM RWST r w s m a > evalRWST = coerce (RWS.evalRWST :: EvalM RWS.RWST r w s m a) > > [...] I should probably mention that the reason I'm having to jump through these hoops with boilerplate code is that neither "mtl", nor "transformers" provide "MonadReader", "MonadWriter", "MonadState" or just "MonadRWS" instances for RWS.CPS, which might otherwise have made it possible to just replace all the coercions with: -- here MyRWST == a newtype-wrapped actual RWS.CPS.RWST deriving instance Monad m => MonadRWS r w s (MyRWST r w s m) along the lines of: https://hackage.haskell.org/package/writer-cps-mtl-0.1.1.6 Are there reasons why MTL cannot or should not do this? Or is this just something that the maintainer have not had a chance to consider or implement? [ The "mtl" MonadWriter type class has a narrower signature for "pass" where the inner monoid is the same as the outer monoid, but that's sufficient for my needs. ] -- Viktor. From anthony_clayden at clear.net.nz Mon May 11 02:21:56 2020 From: anthony_clayden at clear.net.nz (Anthony Clayden) Date: Mon, 11 May 2020 14:21:56 +1200 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? Message-ID: Thanks Irfon-Kim for your research, but you're making this a lot harder than it needs to be. I'll try to redress the balance -- not that I'm claiming it's Windows-friendly. > Yes, you need to know several magic things to go this route. > You don't need to install any extra tools, nor use a command line, nor have a bar of chocolatey. > The first is to have that link that Ben Gamari provided in the first place, which is not an obvious thing at all. I think Ben gave the wrong link[**], and it's not obvious why you'd go to such an unfriendly page at all. Should be: https://www.haskell.org/ghc/download_ghc_8_10_1.html, section Windows 64-bit (x86_64). This is to download ghc-8.10.1-x86_64-unknown-mingw32.tar.xz it's not the 'unknown' that tells you it's Windows, it's the 'w' in 'w32'. I don't know why you're downloading a `.lz`: the `.tar.xz` is a format that Windows Explorer understands [***]; just use Explorer to find that in the Downloads folder; it needs several clicks to unpack it, but by all means unpack into the Downloads folder; navigate to `\bin`; there is ghci.exe; double-click. (No need to set your path, it'll default to `\bin`; no need to call from a command line.) Indeed you can copy ghci.exe and paste as shortcut on your desktop/taskbar; set the 'Start in' as the `\bin` folder. Now fair warning: this is only the ghci executable/base compiler; no libraries/packages; no cabal, no stackage. But at least a beginner can sit at a GHCi prompt and enter some expressions; they can call `:edit` to create a `.hs` module. They can `:set editor` for a more programmer-friendly editor. [**] How did I get to that download link? (Just to show there's nothing up my sleeves) * haskell.org -> Downloads -> Minimal Installers * -> 'the GHC compiler' in the section's opening sentence * you're at haskell.org/ghc/; latest release -> download * scan down the page for Windows I'm saying to ignore all that stuff about 'proper Haskell distribution'; 'Distribution packages' (not available for Windows). For a beginner it's all cruft; they can figure it out after they're using Haskell. Really this could all be a lot easier and a lot better explained and a lot more in-your-face for a beginner. I continue to take away the impression that ghc doesn't want beginners. [***] I agree a `.xz` needs 7-zip to unpack. I don't think I went so far as to obtain that first; I think it came with my Windows (8.1) install. Perhaps later Windows have it better integrated(?) -------------- next part -------------- An HTML attachment was scrubbed... URL: From svenpanne at gmail.com Mon May 11 07:08:10 2020 From: svenpanne at gmail.com (Sven Panne) Date: Mon, 11 May 2020 09:08:10 +0200 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: References: Message-ID: Am Mo., 11. Mai 2020 um 04:24 Uhr schrieb Anthony Clayden < anthony_clayden at clear.net.nz>: > [...] You don't need to install any extra tools, nor use a command line, nor have a bar of chocolatey. > > Actually, you *do* need to install an extra tool to unpack xz files. > [...] I don't know why you're downloading a `.lz`: the `.tar.xz` is a format that Windows Explorer understands [***]; just use Explorer to find [...] > > The Windows Explorer understands it only if you have e.g. 7z or WinZip installed. > [***] I agree a `.xz` needs 7-zip to unpack. I don't think I went so far as to obtain that first; I think it came with my Windows (8.1) install. Perhaps later Windows have it better integrated(?) > > You probably have remnants of 7z or WinZip on your disk after updating from previous Windows versions. I very much doubt that a fresh Windows 10 installation has the slightest clue what an xz file is. Let's be honest: Everything which is not an MSI, or a self-installing .exe or a ZIP-file (for position-independent stuff) is a ridiculous, totally non-standard way of installing SW on Windows, scaring away tons of potential users. Small obstacles like this should not be underestimated, there are impressive numbers from e.g. the usability/success of web sites: Every user interaction, like a click or even just scrolling down the page, makes you lose a magnitude of your potential customers. 2 clicks + 1 scrolling? => 0.1% of your customers left... Let's look at a few other programming languages on Windows: * Python: Fat download button, leading quickly to a choice of self-installing .exe, ZIP or a web-based installer. And this was just python.org... * Racket: Again a self-installing .exe, 2 klicks away from the fat download button on the start page. Hey, you even get a decent IDE with that! * Rust: You are only a few clicks away from having rustup on your disk. * Ruby: You are quickly on rubyinstaller.org with a choice of self-installing .exes. * Perl: You can quickly choose between two installers, e.g. http://strawberryperl.com/ with MSI or ZIP * Clang: Only a few clicks away from a self-installing .exe. * Node.js: An MSI is only few clicks away. Does any other language require you to install tools to unpack alien archive formats or even a full-fledged package manager? No... It is totally fine that there are more complicated and more flexible ways to install a language for the power user, but that's optional. What is *not* optional is an easy, native way of installation for the casual user. For my part, I would already be happy if stack would get a more prominent place and be promoted as *the* way to install Haskell. But the stackage releases would need to follow the GHC releases a bit more quickly then (there is still no stackage with GHC 8.10 :-( ). -------------- next part -------------- An HTML attachment was scrubbed... URL: From jack at jackkelly.name Mon May 11 07:55:01 2020 From: jack at jackkelly.name (Jack Kelly) Date: Mon, 11 May 2020 17:55:01 +1000 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: (Sven Panne's message of "Mon, 11 May 2020 09:08:10 +0200") References: Message-ID: <87tv0mj48a.fsf@jackkelly.name> Sven Panne writes: > Am Mo., 11. Mai 2020 um 04:24 Uhr schrieb Anthony Clayden < > anthony_clayden at clear.net.nz>: > > Let's be honest: Everything which is not an MSI, or a self-installing .exe > or a ZIP-file (for position-independent stuff) is a ridiculous, totally > non-standard way of installing SW on Windows, scaring away tons of > potential users. Small obstacles like this should not be underestimated, > there are impressive numbers from e.g. the usability/success of web sites: > Every user interaction, like a click or even just scrolling down the page, > makes you lose a magnitude of your potential customers. 2 clicks + 1 > scrolling? => 0.1% of your customers left... I value a good installation story for Windows, but do not have the time or familiarity with Windows to meaningfully contribute. Is there anywhere I can donate to that would help this cause in particular? -- Jack From mgajda at mimuw.edu.pl Mon May 11 14:51:20 2020 From: mgajda at mimuw.edu.pl (Michal J Gajda) Date: Mon, 11 May 2020 16:51:20 +0200 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? Message-ID: Hi, I recently installed GHC using Chocolatey, since an user requested Windows support. I understand that the new installation mode allows to use package manager on the platform that lacks native package manager support. It took me approximately an hour in total, since the process of compiling a Haskell program required: 1. To install and find powershell, and run it as administrator. (If you try to install Chocolatey as non-admin user you get a long error message.) 2. To use powershell console to change some default Chocolatey options so that it does not stop each time that configuration change is requested. 3. To enter relevant command line in admin PowerShell so that Chocolatey installs GHC. 4. Ditto for Mingw (3 attempts, since I think default Mingw package lacks full build environment.) 4. Ditto for every dependency of my Haskell package. (Is there a way to get standardized library dependencies across the platforms? Drop me a line if it is at all possible without Nix.) 5. Installing Haskell Stack, since I gave up making it work with Cabal install+chocolatey at this point. 6. Building everything with Haskell stack in powershell to acquire environment settings that expose the dependent libraries. Maybe we need a wizard app that takes us through the process? I am certain that part of the pain was due to the fact that I rarely use Windows platform. Did we diverge so far from Windows, because everybody moved to the cloud-based Linux builds? I guess, if not for using Stack, I was about half-way to get install process running. I wonder how to support Windows build environment best. Is there maybe Ansible setup script for barebones Windows environment? -- Cheers Michał From lexi.lambda at gmail.com Mon May 11 18:30:19 2020 From: lexi.lambda at gmail.com (Alexis King) Date: Mon, 11 May 2020 13:30:19 -0500 Subject: [Haskell-cafe] Missing mil classes for RWST.CPS (was: Coercing newtype-wrapped monad transformers?) In-Reply-To: References: <20200510042723.GC76674@straasha.imrryr.org> <20200510192056.GF76674@straasha.imrryr.org> Message-ID: <6E041C88-B1FC-48F4-9421-C9AD722943DA@gmail.com> > On May 10, 2020, at 19:55, Viktor Dukhovni wrote: > > I should probably mention that the reason I'm having to jump through these > hoops with boilerplate code is that neither "mtl", nor "transformers" provide > "MonadReader", "MonadWriter", "MonadState" or just "MonadRWS" instances for > RWS.CPS, The instances are already present on master (I added them) but they have not yet been released to Hackage. Remarkably, mtl seems to be without a maintainer. See https://github.com/haskell/mtl/issues/69 . Alexis -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Mon May 11 19:20:23 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Mon, 11 May 2020 15:20:23 -0400 Subject: [Haskell-cafe] Missing mtl classes for RWST.CPS (was: Coercing newtype-wrapped monad transformers?) In-Reply-To: <6E041C88-B1FC-48F4-9421-C9AD722943DA@gmail.com> References: <20200510042723.GC76674@straasha.imrryr.org> <20200510192056.GF76674@straasha.imrryr.org> <6E041C88-B1FC-48F4-9421-C9AD722943DA@gmail.com> Message-ID: <5BA522B1-3553-45CB-9537-CA01F990DAE2@dukhovni.org> > On May 11, 2020, at 2:30 PM, Alexis King wrote: > >> I should probably mention that the reason I'm having to jump through these >> hoops with boilerplate code is that neither "mtl", nor "transformers" provide >> "MonadReader", "MonadWriter", "MonadState" or just "MonadRWS" instances for >> RWS.CPS, > > The instances are already present on master (I added them) but they have not yet been > released to Hackage. Remarkably, mtl seems to be without a maintainer. See > https://github.com/haskell/mtl/issues/69. Thanks! Good to know these are at least in the pipeline. Perhaps some day I'll get to trim the boilerplate down to just: "deriving instance MonadRWS". Good luck finding someone to cut the release... -- Viktor. From gershomb at gmail.com Tue May 12 06:59:04 2020 From: gershomb at gmail.com (Gershom B) Date: Tue, 12 May 2020 02:59:04 -0400 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? Message-ID: On May 11, 2020 at 10:52:36 AM, Michal J Gajda (mgajda at mimuw.edu.pl) wrote: > 3. To enter relevant command line in admin PowerShell so that Chocolatey installs GHC. > 4. Ditto for Mingw (3 attempts, since I think default Mingw package lacks full build environment.) > 4. Ditto for every dependency of my Haskell package. (Is there a way to get standardized library dependencies across the platforms? Drop me a line if it is at all possible without Nix.) I’m confused. When you used chocolatey, why did you not run “choco install haskell-dev” as suggested on https://www.haskell.org/platform/#windows (and i imagine everywhere else)? This should have installed ghc, msys2 and cabal for you at once. Further what do you mean "Ditto for every dependency of my Haskell package” — do you mean haskell dependencies or c dependencies? If the latter, how is this different than any other OS? Also, why were you installing c dependencies with chocolatey, if that’s indeed what you were doing? With msys2 the way to do things is install them with pacman. Perhaps what is needed is just better and more centralized documentation? -g -------------- next part -------------- An HTML attachment was scrubbed... URL: From mgajda at mimuw.edu.pl Tue May 12 08:21:20 2020 From: mgajda at mimuw.edu.pl (Michal J Gajda) Date: Tue, 12 May 2020 10:21:20 +0200 Subject: [Haskell-cafe] When did it become so hard to install Haskell on Windows? In-Reply-To: References: Message-ID: Suppose I missed the part how to install updated `haskell-dev` with specific compiler version. (Asking for specific compiler version is best current practice AFAIK.) On Tue, May 12, 2020, 08:59 Gershom B wrote: > On May 11, 2020 at 10:52:36 AM, Michal J Gajda (mgajda at mimuw.edu.pl) > wrote: > > > 3. To enter relevant command line in admin PowerShell so that > Chocolatey installs GHC. > > 4. Ditto for Mingw (3 attempts, since I think default Mingw package > lacks full build environment.) > > 4. Ditto for every dependency of my Haskell package. (Is there a way > to get standardized library dependencies across the platforms? Drop me > a line if it is at all possible without Nix.) > > I’m confused. When you used chocolatey, why did you not run “choco install > haskell-dev” as suggested on https://www.haskell.org/platform/#windows (and > i imagine everywhere else)? This should have installed ghc, msys2 and cabal > for you at once. > > Further what do you mean "Ditto for every dependency of my Haskell > package” — do you mean haskell dependencies or c dependencies? If the > latter, how is this different than any other OS? Also, why were you > installing c dependencies with chocolatey, if that’s indeed what you were > doing? With msys2 the way to do things is install them with pacman. > > Perhaps what is needed is just better and more centralized documentation? > > -g > -------------- next part -------------- An HTML attachment was scrubbed... URL: From leo at lpw25.net Tue May 12 18:16:29 2020 From: leo at lpw25.net (Leo White) Date: Tue, 12 May 2020 19:16:29 +0100 Subject: [Haskell-cafe] ML Family Workshop 2020: Deadline extension Message-ID: <7c3dc502-3b3b-4af1-a414-ee2c9717bd54@www.fastmail.com> Due to the COVID-19 pandemic, ML 2020 will take place online. The submission deadline has been extended to the end of the month to accommodate for the change in situation. ============================================================= We are happy to invite submissions to the ML Family Workshop 2020, to be held during the ICFP conference week on Thursday, August 27th. The ML family workshop warmly welcomes submission touching on the programming languages traditionally seen as part of the "ML family" (Standard ML, OCaml, F#, CakeML, SML#, Manticore, MetaOCaml, etc.). The scope of the workshop includes all aspects of the design, semantics, theory, application, implementation, and teaching of the members of the ML family. We also encourage presentations from related languages (such as Haskell, Scala, Rust, Nemerle, Links, Koka, F*, Eff, ATS, etc), to exchange experience of further developing ML ideas. Due to the COVID-19 pandemic, the workshop will take place online. See our detailed CFP online on the ICFP website: https://icfp20.sigplan.org/home/mlfamilyworkshop-2020 Important dates --------------- - Friday 29th May (any time zone): Abstract submission deadline - Friday 17th July: Author notification - Thursday 27th August: ML Family Workshop Program committee ----------------- - Youyou Cong (Tokyo Institute of Technology) - Ivan Gotovchits (Carnegie Mellon University) - Gowtham Kaki (Purdue University) - Neel Krishnaswami (University of Cambridge) - Daan Leijen (Microsoft Research) - Koko Muroya (Kyoto University) - Atsushi Ohori (Tohoku University) - Jonathan Protzenko (Microsoft Research) - Gabriel Radanne (INRIA) - Claudio Russo (Dfinity) - Leo White (Jane Street) (Chair) - Jeremy Yallop (University of Cambridge) Submission details ------------------ See the online CFP for the details on the expected submission format. Submissions must be uploaded to the workshop submission website https://ml2020.hotcrp.com/ before the submission deadline. From lemming at henning-thielemann.de Tue May 12 20:55:08 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 12 May 2020 22:55:08 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <517044fa-4fb2-cde6-3a8c-b1013f7b06f0@nh2.me> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> <517044fa-4fb2-cde6-3a8c-b1013f7b06f0@nh2.me> Message-ID: On Fri, 8 May 2020, Niklas Hambüchen wrote: >> What are "unintended exceptions"? >> What is an example of an "unintended exception"? > > A recent example from my production server: > > hPutBuf: resource vanished (Broken pipe) Ok, I lookup the Haddock comment of hPutBuf and it says: "This operation may fail with: * ResourceVanished if the handle is a pipe or socket, and the reading end is closed." That is, ResourceVanished is part of the public interface and in no way unexpected (or what "unintended" may be). I would prefer to make this explicit in the type of hPutBuf: hPutBuf :: (ResourceVanishedException e) => Handle -> Ptr a -> Int -> ExceptT e IO () Now, what do you intend to do with the call-stack? Isn't it something you can attach to the e value? From lemming at henning-thielemann.de Tue May 12 21:06:35 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 12 May 2020 23:06:35 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <87mu6i1eyw.fsf@smart-cactus.org> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <87mu6i1eyw.fsf@smart-cactus.org> Message-ID: On Fri, 8 May 2020, Ben Gamari wrote: > We can debate whether partial functions like `fromJust` should exist; however, > the fact of the matter is that they do exist and they are used. That's not my point. I say: fromJust on Nothing is a programming error, ok. We must debug this. HasCallStack helps here. However, it does not have to do with exceptions or with the proposals as I understand them. > Furthermore, even `base`'s own IO library (e.g. `openFile`) uses > synchronous exceptions to report errors. Right. I say: Such exceptions are part of the public interface and should be expressed in types. If you encounter any problems when not doing this, I would first try to solve the problem with exceptions explicit in the type. E.g. Haddock for openFile says: This operation may fail with: * isAlreadyInUseError ... * isDoesNotExistError ... * isPermissionError ... Thus the type should be: openFile :: (AlreadyInUseException e, DoesNotExistException e, PermissionException e) => FilePath -> IOMode -> ExceptT e IO Handle > Perhaps this helps to shed some light on the motivation? Unfortunately no. I only see the immortal confusion about (programming) errors vs. (IO) exceptions. And I think that part of this confusion is that IO exceptions in 'base' are hidden in the IO type and that there are hybrid functions like 'throw' that can be called like 'error' but they cause IO exceptions that can be caught by 'catch'. From lemming at henning-thielemann.de Tue May 12 21:29:19 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 12 May 2020 23:29:19 +0200 (CEST) Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: <87k11m1e9z.fsf@smart-cactus.org> References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> <87k11m1e9z.fsf@smart-cactus.org> Message-ID: On Fri, 8 May 2020, Ben Gamari wrote: > Henning Thielemann writes: > >> We are talking about the HasCallStack stack traces, yes? >> How is their emission addressed by extending exceptions with stack >> traces? > > HasCallStack stack traces are one type of backtrace that the proposal > supports. However, it's not the only (nor is it even the most useful > sort, in my opinion). > > Other mechanisms include cost center stacks from the cost-center > profiler and native stack unwinding. Interesting. That's a completely new thing. >>> * Developers cannot easily produce stack traces do debug unintended >>> exceptions. >> >> What are "unintended exceptions"? >> What is an example of an "unintended exception"? > > For instance, > > * Somewhere deep in my code a colleague used `fromJust` due to a > miscommunicated invariant That's a programming error. > * Somewhere in my system a `writeFile "tmp" $ repeat 'a'` failed due to > filling the disk Hm, that's also a programming error, but it ends in an IO exception. If it would not end in an IO exception (e.g. writing to /dev/null) it would go to an infinite loop. Anyway, it is a programming error. However it is an unchecked one. That is, there is no warranty that you can catch it by a debugger. So I do not think you can achieve much with callstacks here. > * Somewhere in my system I have a partial pattern match in a module > which was compiled without -Wall Programming error and btw. before thinking about a GHC extension I would enable -Wall ... > * Somewhere in my system I `div` by zero due to lack of input > validation Programming error > * I use a record selector on a sum. Programming error > * A logic error results in an assertion failure deep in my program, but > it's unclear which path my program took to arrive at the assertion Sounds like Programming error > This list could go on and on... >From your list of examples I deduce that the proposal is about programming errors. But we have HasCallStack for that one. How does the proposal improve or alter the HasCallStack solution? And how does it relate to the IO exception system with hierarchical exceptions and SomeException and so on? > Currently the proposal does not cover asynchronous exceptions but it > wouldn't be particularly hard to extend it in this direction. This would > allow far better reporting of heap/stack overflows and MVar deadlocks > (which are particularly hard to debug at the moment). Hm, what kind of heap or stack overflow are you thinking of? A stack overflow sounds like unlimited recursion and thus like a programming error. In contrast to that, a program must be prepared for a failure of "malloc". Memory exhaustion is an IO exception, it should be explicit in the type. Are MVar deadlocks always detected by the runtime system? From mail at nh2.me Tue May 12 22:14:30 2020 From: mail at nh2.me (=?UTF-8?Q?Niklas_Hamb=c3=bcchen?=) Date: Wed, 13 May 2020 00:14:30 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> <517044fa-4fb2-cde6-3a8c-b1013f7b06f0@nh2.me> Message-ID: On 5/12/20 10:55 PM, Henning Thielemann wrote: > "This operation may fail with: > > * ResourceVanished if the handle is a pipe or socket, and the reading end is closed." > > That is, ResourceVanished is part of the public interface and in no way unexpected (or what "unintended" may be). I would prefer to make this explicit in the type of hPutBuf: > > hPutBuf :: >    (ResourceVanishedException e) => >    Handle -> Ptr a -> Int -> ExceptT e IO () > > Now, what do you intend to do with the call-stack? Isn't it something you can attach to the e value? Why is this relevant? The point of debugging is to find programming errors. It does not matter what the Haddocks say; if a programmer uses the function wrong, the exception will occur. hPutBuf does not currently have that type, nor can anybody rewrite all the existing libraries easily. The point of the proposal is to make the RTS help us debug problems in code as it exists today. From ruben.astud at gmail.com Wed May 13 05:35:52 2020 From: ruben.astud at gmail.com (Ruben Astudillo) Date: Wed, 13 May 2020 01:35:52 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) Message-ID: <332a907e-2035-a1e7-676d-82fa10e9d602@gmail.com> Hello cafe I've been doing some basic logic exercises on Haskell the last few days. Along the way I learned about intuitionistic logic and double negation. On STLC types are propositions and terms of those types are proofs of those propositions. The standard way to negate a proposition/type ~A~ in Haskell is via the type type Not a = a -> Void So far so good. On classical logic we have an equivalence between a proposition and it's double negation. On intuitionistic logic I only have a single implication that ~forall a. a -> Not (Not a)~, this is easy to see as we have the proof/term proof :: forall a. a -> Not (Not a) proof a = \cont -> cont a But we don't have the implication between ~forall a. Not (Not a) -> a~, there is no way to obtain an ~a~ from the void continuations. Worse than that, to even use such continuation I would need to have an ~a~ already. On blogposts I've seen the claim that the types ~Void~ and ~forall a. a~ are almost the same. I can see the second one only has bottom as a term. H98 versions of Void also had that term. The curious fact is that people treat them as if they were the same without questioning. But they are not the same, we can see this as there is an implication ~(forall r. (a -> r) -> r) -> a~ given by the proof proof1 :: forall a. (forall r. (a -> r) -> r) -> a proof1 cont = cont id That leads me to believe that given that ~(forall r. (a -> r) -> r)~ and ~(a -> Void) -> Void)~ are not obviously the same, the relationship between ~Void~ and ~forall a. a~ is not as people say. So cafe, how can I reconcile these facts? -- -- Rubén -- pgp: 4EE9 28F7 932E F4AD -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From david.feuer at gmail.com Wed May 13 05:44:42 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 13 May 2020 01:44:42 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: <332a907e-2035-a1e7-676d-82fa10e9d602@gmail.com> References: <332a907e-2035-a1e7-676d-82fa10e9d602@gmail.com> Message-ID: You're misplacing your quantifiers. (a -> Void) -> Void) is not isomorphic to forall r. (a -> r) -> r but *is* isomorphic to (a -> (forall r. r)) -> (forall r. r) which we'd normally write something like forall r. (forall q. a -> q) -> r On Wed, May 13, 2020, 1:36 AM Ruben Astudillo wrote: > Hello cafe > > I've been doing some basic logic exercises on Haskell the last few days. > Along the way I learned about intuitionistic logic and double negation. > On STLC types are propositions and terms of those types are proofs of > those propositions. The standard way to negate a proposition/type ~A~ in > Haskell is via the type > > type Not a = a -> Void > > So far so good. On classical logic we have an equivalence between a > proposition and it's double negation. On intuitionistic logic I only > have a single implication that ~forall a. a -> Not (Not a)~, this is > easy to see as we have the proof/term > > proof :: forall a. a -> Not (Not a) > proof a = \cont -> cont a > > But we don't have the implication between ~forall a. Not (Not a) -> a~, > there is no way to obtain an ~a~ from the void continuations. Worse than > that, to even use such continuation I would need to have an ~a~ already. > > On blogposts I've seen the claim that the types ~Void~ and ~forall a. a~ > are almost the same. I can see the second one only has bottom as a term. > H98 versions of Void also had that term. The curious fact is that people > treat them as if they were the same without questioning. > > But they are not the same, we can see this as there is an implication > ~(forall r. (a -> r) -> r) -> a~ given by the proof > > proof1 :: forall a. (forall r. (a -> r) -> r) -> a > proof1 cont = cont id > > That leads me to believe that given that ~(forall r. (a -> r) -> r)~ and > ~(a -> Void) -> Void)~ are not obviously the same, the relationship > between ~Void~ and ~forall a. a~ is not as people say. > > So cafe, how can I reconcile these facts? > > -- > -- Rubén > -- pgp: 4EE9 28F7 932E F4AD > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Wed May 13 06:47:36 2020 From: compl.yue at icloud.com (YueCompl) Date: Wed, 13 May 2020 14:47:36 +0800 Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early Message-ID: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> Folks, I need a little help, I remember I had read some where that, there's a function to fake a use of a value, so it won't be garbage collected too early, as GHC has an optimization to forget a value as early as possible. But I can't remember the function name or even the keyword to google it out, hint me please! Best regards, Compl From david.feuer at gmail.com Wed May 13 06:52:43 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 13 May 2020 02:52:43 -0400 Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early In-Reply-To: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> References: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> Message-ID: You're looking for the `touch` function. I don't remember where it lives. I believe there's also a new and improved replacement whose name I don't remember. On Wed, May 13, 2020, 2:47 AM YueCompl via Haskell-Cafe < haskell-cafe at haskell.org> wrote: > Folks, > > I need a little help, I remember I had read some where that, there's a > function to fake a use of a value, so it won't be garbage collected too > early, as GHC has an optimization to forget a value as early as possible. > But I can't remember the function name or even the keyword to google it > out, hint me please! > > Best regards, > Compl > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From compl.yue at icloud.com Wed May 13 07:03:58 2020 From: compl.yue at icloud.com (YueCompl) Date: Wed, 13 May 2020 15:03:58 +0800 Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early In-Reply-To: References: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> Message-ID: <3ABE5D7E-58E6-45FB-AB5A-97D00FC9062D@icloud.com> Thanks! I found `touch` in `Control.Monad.Primitive` , and repa even requires an array element type to implement `Elt` which mainly asking for the `touch` method. It's interesting to know there's even more improvement on it. > On 2020-05-13, at 14:52, David Feuer wrote: > > You're looking for the `touch` function. I don't remember where it lives. I believe there's also a new and improved replacement whose name I don't remember. > > On Wed, May 13, 2020, 2:47 AM YueCompl via Haskell-Cafe > wrote: > Folks, > > I need a little help, I remember I had read some where that, there's a function to fake a use of a value, so it won't be garbage collected too early, as GHC has an optimization to forget a value as early as possible. But I can't remember the function name or even the keyword to google it out, hint me please! > > Best regards, > Compl > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From sylvain at haskus.fr Wed May 13 07:28:28 2020 From: sylvain at haskus.fr (Sylvain Henry) Date: Wed, 13 May 2020 09:28:28 +0200 Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early In-Reply-To: <3ABE5D7E-58E6-45FB-AB5A-97D00FC9062D@icloud.com> References: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> <3ABE5D7E-58E6-45FB-AB5A-97D00FC9062D@icloud.com> Message-ID: The primitive is `touch#` (https://www.stackage.org/haddock/lts-15.12/base-4.13.0.0/GHC-Exts.html#v:touch-35-) It's quite fragile (e.g. can be optimized away or moved), so we're trying to replace it with something else. See https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/with-combinator On 13/05/2020 09:03, YueCompl via Haskell-Cafe wrote: > Thanks! I found `touch` in `Control.Monad.Primitive` , and repa even > requires an array element type to implement `Elt` which mainly asking > for the `touch` method. > > It's interesting to know there's even more improvement on it. > >> On 2020-05-13, at 14:52, David Feuer > > wrote: >> >> You're looking for the `touch` function. I don't remember where it >> lives. I believe there's also a new and improved replacement whose >> name I don't remember. >> >> On Wed, May 13, 2020, 2:47 AM YueCompl via Haskell-Cafe >> > wrote: >> >> Folks, >> >> I need a little help, I remember I had read some where that, >> there's a function to fake a use of a value, so it won't be >> garbage collected too early, as GHC has an optimization to forget >> a value as early as possible. But I can't remember the function >> name or even the keyword to google it out, hint me please! >> >> Best regards, >> Compl >> >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. >> >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Wed May 13 09:00:08 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Wed, 13 May 2020 11:00:08 +0200 (CEST) Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early In-Reply-To: References: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> <3ABE5D7E-58E6-45FB-AB5A-97D00FC9062D@icloud.com> Message-ID: On Wed, 13 May 2020, Sylvain Henry wrote: > It's quite fragile (e.g. can be optimized away or moved), so we're trying to replace it with something else. See > https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/with-combinator I remember that the fragility due to optimization is quite a problem. I found that creating a StablePtr is reliable, however. From ben at smart-cactus.org Wed May 13 12:41:40 2020 From: ben at smart-cactus.org (Ben Gamari) Date: Wed, 13 May 2020 08:41:40 -0400 Subject: [Haskell-cafe] Way to prevent a value from being garbage collected too early In-Reply-To: References: <48881626-6CEA-4899-9968-A53232F33B73@icloud.com> <3ABE5D7E-58E6-45FB-AB5A-97D00FC9062D@icloud.com> Message-ID: <69158377-A3CB-4398-9B1A-93C7A1066577@smart-cactus.org> On May 13, 2020 5:00:08 AM EDT, Henning Thielemann wrote: > >On Wed, 13 May 2020, Sylvain Henry wrote: > >> It's quite fragile (e.g. can be optimized away or moved), so we're >trying to replace it with something else. See >> https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/with-combinator > >I remember that the fragility due to optimization is quite a problem. I > >found that creating a StablePtr is reliable, however. >_______________________________________________ >Haskell-Cafe mailing list >To (un)subscribe, modify options or view archives go to: >http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >Only members subscribed via the mailman list are allowed to post. Yes, but do note that the latter of significantly more expensive. Cheers, — Ben From olf at aatal-apotheke.de Wed May 13 13:15:15 2020 From: olf at aatal-apotheke.de (Olaf Klinke) Date: Wed, 13 May 2020 15:15:15 +0200 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) Message-ID: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> > You're misplacing your quantifiers. > > (a -> Void) -> Void) > > is not isomorphic to > > forall r. (a -> r) -> r > > but *is* isomorphic to > > (a -> (forall r. r)) -> (forall r. r) > ...which is because you could _define_ Void to be (forall r. r): {-# LANGUAGE Rank2Types #-} newtype Void = Void {absurd :: forall r. r} In practice, Void used to be implemented as data Void = Void Void before it became just data Void by means of EmptyDataDecls extension. The latter has the advantage that there is no constructor named 'Void'. In reality of course, Void does have an element, bottom, which it shares with all other types. Hence the 'absurd' function that returns the bottom in type r when given the bottom in type Void. But as you know the correspondence between types and theorems in intuitionistic logic explicitly regards only total values. Excersise: Prove that intuitionistically, it is absurd to deny the law of excluded middle: Not (Not (Either a (Not a))) There is a whole world to be discovered beneath the total values. Think about the type () as truth values and what universal quantification could be. Olaf From ben.franksen at online.de Wed May 13 13:52:18 2020 From: ben.franksen at online.de (Ben Franksen) Date: Wed, 13 May 2020 15:52:18 +0200 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <87mu6i1eyw.fsf@smart-cactus.org> Message-ID: Am 12.05.20 um 23:06 schrieb Henning Thielemann: > Thus the type should be: > > openFile :: >    (AlreadyInUseException e, >     DoesNotExistException e, >     PermissionException e) => >    FilePath -> IOMode -> ExceptT e IO Handle Yes, but then these errors would no longer be exceptions but normal return values (if you remove the ExceptT veneer). So what you say amounts to "exceptions should be removed from Haskell except for programming errors". I agree that communicating IO errors (and similar things) explicitly ie. via return value is the better choice. But the proposal is about Haskell (the language and standard libraries) as it presently is i.e. the one that uses exceptions for IO errors, not the one you want to have and in which IO errors are communicated as return values and openFile would have the type above. And that means your objection to the proposal at hand is irrelevant and beside the point. From Erwan.Bousse at ls2n.fr Wed May 13 14:52:48 2020 From: Erwan.Bousse at ls2n.fr (Erwan BOUSSE) Date: Wed, 13 May 2020 16:52:48 +0200 Subject: [Haskell-cafe] =?utf-8?q?CFP=3A_GPCE_2020_=E2=88=92_19th_Internat?= =?utf-8?q?ional_Conference_on_Generative_Programming=3A_Concepts_=26_Expe?= =?utf-8?q?riences?= Message-ID: ----------------------------------------------------------------------- GPCE 2020: 19th International Conference on Generative Programming: Concepts & Experiences November 16-17, 2020 Chicago, IL (USA) (a part of the SPLASH series of conferences) https://conf.researchr.org/home/gpce-2020 ----------------------------------------------------------------------- --------------------------- CALL FOR PAPERS --------------------------- The ACM SIGPLAN International Conference on Generative Programming: Concepts & Experiences is a programming languages conference focusing on techniques and tools for code generation, language implementation, and product-line development. GPCE seeks conceptual, theoretical, empirical, and technical contributions to its topics of interest, which include but are not limited to: program transformation, staging, macro systems, preprocessors, program synthesis, and code-recommendation systems, domain-specific languages, language embedding, language design, and language workbenches, feature-oriented programming, domain engineering, and feature interactions, applications and properties of code generation, language implementation, and product-line development. Authors are welcome to check with the PC chair whether their planned papers are in scope. --------------------------- IMPORTANT DATES --------------------------- - Abstract submission: July 20, 2020 (Monday), AoE - Paper submission: July 27, 2020 (Monday), AoE - Author notification: September 9, 2020 (Wednesday) - Conference: November 16-17, 2020 --------------------------- PAPER SELECTION --------------------------- The GPCE program committee will evaluate each submission according to the following selection criteria: - Novelty. Papers must present new ideas or evidence and place them appropriately within the context established by previous research in the field. - Significance. The results in the paper must have the potential to add to the state of the art or practice in significant ways. - Evidence. The paper must present evidence supporting its claims. Examples of evidence include formalizations and proofs, implemented systems, experimental results, statistical analyses, and case studies. - Clarity. The paper must present its contributions and results clearly. --------------------------- PAPER CATEGORIES --------------------------- GPCE solicits three kinds of submissions: - Full Papers reporting original and unpublished results of research that contribute to scientific knowledge in any GPCE topic listed above. Full paper submissions must not exceed 12 pages excluding bibliography. - Short Papers presenting unconventional ideas or visions about any GPCE topic listed above. Short papers do not always require complete results as in the case of a full paper. In this way, authors can introduce new ideas to the community and get early feedback. Please note that short papers are not intended to be position statements. Short papers are included in the proceedings and will be presented at the conference. Short paper submissions must not exceed 6 pages excluding bibliography. Short papers must have the text “(Short Paper)” appended to their title, though any papers of 6 or fewer pages that are not tool demonstration papers will be considered as short papers. - Tool Demonstrations presenting tools for any GPCE topic listed above. Tools must be available for use and must not be purely commercial. Submissions must provide a tool description not exceeding 6 pages excluding bibliography and a separate demonstration outline including screenshots also not exceeding 6 pages. Tool demonstrations must have the keywords “Tool Demo” or “Tool Demonstration” appended in their title. If the submission is accepted, the tool description will be published in the proceedings. The demonstration outline will only be used by the program committee for evaluating the submission. --------------------------- PAPER SUBMISSION --------------------------- All submissions must use the ACM SIGPLAN Conference Format “acmart” (http://sigplan.org/Resources/Author/#acmart-format). Please be sure to use the latest LaTeX templates and class files. the SIGPLAN sub-format, and 10 point font. Consult the sample-sigplan.tex template and use the document-class \documentclass[sigplan,anonymous,review]{acmart}. Please do not make any changes to this format! To increase fairness in reviewing, a double-blind review process has become standard across SIGPLAN conferences. GPCE will follow a very lightweight model, where author identities are revealed to reviewers after submitting their initial reviews. Hence, the purpose is not to conceal author identities at all cost, but merely to provide reviewers with an unbiased first look at a submission. Author names and institutions should be omitted from submitted papers, and references to the authors’ own related work should be in the third person. No other changes are necessary, and authors will not be penalized if reviewers are able to infer their identities in implicit ways. Papers must be submitted using HotCRP: https://gpce2020.hotcrp.com/ The official publication date is the date the proceedings are made available in the ACM Digital Library. Papers must describe work not currently submitted for publication elsewhere as described by the SIGPLAN Republication Policy (http://www.sigplan.org/Resources/Policies/Republication/). --------------------------- ORGANIZATION --------------------------- - Steering Committee Chair: Ulrik Pagh Schultz (Denmark) - General Chair: Martin Erwig (USA) - Program Chair: Jeff Gray (USA) - Publicity Chair: Erwan Bousse (France) For additional information, clarification, or answers to questions please contact the program chair at gray at cs.ua.edu --------------------------- PROGRAM COMMITTEE --------------------------- - Juliana Alves Pereira (Brazil) - Ira Baxter (USA) - Don Batory (USA) - Sandrine Blazy (France) - Sheng Chen (USA) - Shigeru Chiba (Japan) - Thomas Degueule (France) - Robert Glück (Denmark) - Aniruddha Gokhale (USA) - Elisa Gonzalez Boix (Belgium) - Julia Lawall (France) - Geoffrey Mainland (USA) - Marjan Mernik (Slovenia) - Bruno Oliveira (Hong Kong) - Alex Potanin (New Zealand) - Suman Roychoudhury (India) - Christoph Seidl (Denmark) - Michel Steuwer (UK) - Eli Tilevich (USA) - Naoyasu Ubayashi (Japan) - Tijs van der Storm (Netherlands) - Vadim Zaytsev (Netherlands) From twhitehead at gmail.com Thu May 14 16:06:37 2020 From: twhitehead at gmail.com (Tyson Whitehead) Date: Thu, 14 May 2020 12:06:37 -0400 Subject: [Haskell-cafe] Decorating exceptions with backtrace information In-Reply-To: References: <87r1vv1kdx.fsf@smart-cactus.org> <0c11ba4f-90af-b56e-e21d-6c4b1eba9144@nh2.me> <56a36bd0-3c98-29fd-ad26-8ca4f99d8d66@nh2.me> <87k11m1e9z.fsf@smart-cactus.org> Message-ID: On Tue, 12 May 2020 at 17:30, Henning Thielemann < lemming at henning-thielemann.de> wrote: > From your list of examples I deduce that the proposal is about programming > errors. But we have HasCallStack for that one. How does the proposal > improve or alter the HasCallStack solution? And how does it relate to the > IO exception system with hierarchical exceptions and SomeException and so > on? > As a parallel item, maybe it would be good if incomplete patterns could have a HasCallStack constraint so the current "Non-exaustive patterns in function foo" message could be extended with a helpful backtrace? If a programmer doesn't want this, then they could use complete matches? -------------- next part -------------- An HTML attachment was scrubbed... URL: From ruben.astud at gmail.com Fri May 15 09:19:01 2020 From: ruben.astud at gmail.com (Ruben Astudillo) Date: Fri, 15 May 2020 05:19:01 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: On 13-05-20 09:15, Olaf Klinke wrote: > Excersise: Prove that intuitionistically, it is absurd to deny the law > of excluded middle: > > Not (Not (Either a (Not a))) It took me a while but it was good effort. I will try to explain how I derived it. We need a term for proof :: Not (Not (Either a (Not a))) proof :: (Either a (Not a) -> Void) -> Void A first approximation is -- Use the (cont :: Either a (Not a) -> Void) to construct the Void -- We need to pass it an Either a (Not a) proof :: (Either a (Not a) -> Void) -> Void proof cont = cont $ Left Damn, we can't use the `Left` constructor as we are missing an `a` value to fill with. Let's try with `Right` proof :: (Either a (Not a) -> Void) -> Void proof cont = cont $ Right (\a -> cont (Left a)) Mind bending. But it does make sense, on the `Right` constructor we assume we are have an `a` but we have to return a `Void`. Luckily we can construct a `Void` retaking the path we were gonna follow before filling with a `Left a`. Along the way I had other questions related to the original mail and given you seem knowledgeable I want to corroborate with you. I've seen claimed on the web that the CPS transform *is* the double negation [1] [2]. I don't think that true, it is almost true in my view. I'll explain, these are the types at hand: type DoubleNeg a = (a -> Void) -> Void type CPS a = forall r. (a -> r) -> r We want to see there is an equivalence/isomorphism between the two types. One implication is trivial proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a proof_CPS_DoubleNeg cont = cont We only specialized `r ~ Void`, which mean we can transform a `CPS a` into a `DoubleNeg a`. So far so good, we are missing the other implication -- bind type variables: a, r -- cont :: (a -> Void) -> Void -- absurd :: forall b. Void -> b -- cc :: a -> r proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) Trouble, we can't fill `_missing :: r -> Void` as such function only exists when `r ~ Void` as it must be the empty function. This is why I don't think `CPS a` is the double negation. But I can see how people can get confused. Given a value `x :: a` we can embed it onto `CPS a` via `return x`. As we saw before we can pass from `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to `DoubleNeg a`, the first one is directly as in the previous mail. The second one is using `proof_CPS_DoubleNeg` embed_onto_DoubleNeg :: a -> DoubleNeg embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return where return :: a -> CPS a return a = ($ a) So CPS is /almost/ the double negation. It is still interesting because it's enough to embed a classical fragment of logic onto the constructive fragment (LEM, pierce etc). But calling it a double negation really tripped me off. Am I correct? Or is there other reason why CPS is called the double negation transformation? Thank for your time reading this, I know it was long. [1]: http://jelv.is/talks/curry-howard.html#slide30 [2]: https://www.quora.com/What-is-continuation-passing-style-in-functional-programming -- -- Rubén -- pgp: 4EE9 28F7 932E F4AD -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From cdsmith at gmail.com Fri May 15 16:04:53 2020 From: cdsmith at gmail.com (Chris Smith) Date: Fri, 15 May 2020 12:04:53 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: This was indeed a fun puzzle to play with. I think this becomes easier to interpret if you factor out De Morgan's Law from the form you posted at the beginning of your email. https://code.world/haskell#PYGDwpaMZ_2iSs74NnwCUrg On Fri, May 15, 2020 at 5:23 AM Ruben Astudillo wrote: > On 13-05-20 09:15, Olaf Klinke wrote: > > Excersise: Prove that intuitionistically, it is absurd to deny the law > > of excluded middle: > > > > Not (Not (Either a (Not a))) > > It took me a while but it was good effort. I will try to explain how I > derived it. We need a term for > > proof :: Not (Not (Either a (Not a))) > proof :: (Either a (Not a) -> Void) -> Void > > A first approximation is > > -- Use the (cont :: Either a (Not a) -> Void) to construct the Void > -- We need to pass it an Either a (Not a) > proof :: (Either a (Not a) -> Void) -> Void > proof cont = cont $ Left > > Damn, we can't use the `Left` constructor as we are missing an `a` value > to fill with. Let's try with `Right` > > proof :: (Either a (Not a) -> Void) -> Void > proof cont = cont $ Right (\a -> cont (Left a)) > > Mind bending. But it does make sense, on the `Right` constructor we > assume we are have an `a` but we have to return a `Void`. Luckily we can > construct a `Void` retaking the path we were gonna follow before filling > with a `Left a`. > > Along the way I had other questions related to the original mail and > given you seem knowledgeable I want to corroborate with you. I've seen > claimed on the web that the CPS transform *is* the double negation [1] > [2]. I don't think that true, it is almost true in my view. I'll > explain, these are the types at hand: > > type DoubleNeg a = (a -> Void) -> Void > type CPS a = forall r. (a -> r) -> r > > We want to see there is an equivalence/isomorphism between the two > types. One implication is trivial > > proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a > proof_CPS_DoubleNeg cont = cont > > We only specialized `r ~ Void`, which mean we can transform a `CPS a` > into a `DoubleNeg a`. So far so good, we are missing the other > implication > > -- bind type variables: a, r > -- cont :: (a -> Void) -> Void > -- absurd :: forall b. Void -> b > -- cc :: a -> r > proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a > proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) > > Trouble, we can't fill `_missing :: r -> Void` as such function only > exists when `r ~ Void` as it must be the empty function. This is why I > don't think `CPS a` is the double negation. > > But I can see how people can get confused. Given a value `x :: a` we can > embed it onto `CPS a` via `return x`. As we saw before we can pass from > `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to > `DoubleNeg a`, the first one is directly as in the previous mail. The > second one is using `proof_CPS_DoubleNeg` > > embed_onto_DoubleNeg :: a -> DoubleNeg > embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return > where > return :: a -> CPS a > return a = ($ a) > > So CPS is /almost/ the double negation. It is still interesting because > it's enough to embed a classical fragment of logic onto the constructive > fragment (LEM, pierce etc). But calling it a double negation really > tripped me off. > > Am I correct? Or is there other reason why CPS is called the double > negation transformation? > > Thank for your time reading this, I know it was long. > > [1]: http://jelv.is/talks/curry-howard.html#slide30 > [2]: > > https://www.quora.com/What-is-continuation-passing-style-in-functional-programming > > -- > -- Rubén > -- pgp: 4EE9 28F7 932E F4AD > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From olf at aatal-apotheke.de Fri May 15 19:20:38 2020 From: olf at aatal-apotheke.de (Olaf Klinke) Date: Fri, 15 May 2020 21:20:38 +0200 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: <34f841f9331af79ff77bc7906ef6ab075c85a453.camel@aatal-apotheke.de> Indeed, Chris, I also could not come up with a proof without use of deMorgan's law. When you remove the type annotations in your code, you obtain an inhabitant of the following type. forall a r. ((Either a (a -> r)) -> r) -> r -- Lemma: reverse of 'either', your deMorgan generalized. un_either :: (Either a b -> c) -> (a -> c,b -> c) un_either f = (f . Left,f . Right) uncurry (flip ($)) . un_either :: (Either a (a -> r) -> r) -> r There is a geometric interpretation of intuitionistic double negation. Consider an open set A on the real line, an interval without end points, say. As it is custom, I will "draw" open intervals with round parentheses. A -----(======)----- Open sets form a Heyting algebra, where (&&) is implemented by set intersection, (||) is implemented by set union and which has an implication (->), but only the laws of intuitionistic logic hold. This correspondence helps me a lot when thinking about terms of the logic. The Heyting negation of an open set on the real line is the interior of the set complement: -----(======)----- A =====]------[===== set complement of A =====)------(===== Not A Here "interior" means the set with all boundary points removed. Now what is a set where Not (Not A) is True? It is "dense", a set that is so fat that when you do the Heyting negation twice, it covers the entire real line. One class of such sets are the real line without a single point: =====)(===== A ------------ Not A ============ Not (Not A) This is because the interior of a single point (the set complement of A) is the empty set, and the complement of the empty set is the entire real line. In that respect you could say that the law of excluded middle is almost true in intuitionistic logic. Heyting negation is a special case of Heyting implication. The Heyting implication A -> B of two open sets A and B is the largest open set C whose intersection with A is contained in B. (Equivalently, the largest C that has the same intersection with A as B has. These definitions also hold for classical implication and the Boolean algebra of all sets.) -----(======)----- A ---------(=====)-- B ---------(==)----- A && B =====)---(======== A -> B Exercise: Convince yourself, using the definition of A -> B given above, that A -> B is the entire real line if and only if A is contained in B. Now consider the types of 'curry' and 'uncurry' and squint a little: 'curry' and 'uncurry' are witnesses for the isomorphism of types ((c,a) -> b) ~ (c -> (a -> b)). Read this as: ( c , a) -> b (c `intersection` a) `contained in` b if and only if c -> (a -> b) c `contained in` (a `implication` b) Olaf On Fri, 2020-05-15 at 12:04 -0400, Chris Smith wrote: > This was indeed a fun puzzle to play with. I think this becomes > easier to > interpret if you factor out De Morgan's Law from the form you posted > at the > beginning of your email. > > https://code.world/haskell#PYGDwpaMZ_2iSs74NnwCUrg > > > On Fri, May 15, 2020 at 5:23 AM Ruben Astudillo < > ruben.astud at gmail.com> > wrote: > > > On 13-05-20 09:15, Olaf Klinke wrote: > > > Excersise: Prove that intuitionistically, it is absurd to deny > > > the law > > > of excluded middle: > > > > > > Not (Not (Either a (Not a))) > > > > It took me a while but it was good effort. I will try to explain > > how I > > derived it. We need a term for > > > > proof :: Not (Not (Either a (Not a))) > > proof :: (Either a (Not a) -> Void) -> Void > > > > A first approximation is > > > > -- Use the (cont :: Either a (Not a) -> Void) to construct the > > Void > > -- We need to pass it an Either a (Not a) > > proof :: (Either a (Not a) -> Void) -> Void > > proof cont = cont $ Left > > > > Damn, we can't use the `Left` constructor as we are missing an `a` > > value > > to fill with. Let's try with `Right` > > > > proof :: (Either a (Not a) -> Void) -> Void > > proof cont = cont $ Right (\a -> cont (Left a)) > > > > Mind bending. But it does make sense, on the `Right` constructor we > > assume we are have an `a` but we have to return a `Void`. Luckily > > we can > > construct a `Void` retaking the path we were gonna follow before > > filling > > with a `Left a`. > > > > Along the way I had other questions related to the original mail > > and > > given you seem knowledgeable I want to corroborate with you. I've > > seen > > claimed on the web that the CPS transform *is* the double negation > > [1] > > [2]. I don't think that true, it is almost true in my view. I'll > > explain, these are the types at hand: > > > > type DoubleNeg a = (a -> Void) -> Void > > type CPS a = forall r. (a -> r) -> r > > > > We want to see there is an equivalence/isomorphism between the two > > types. One implication is trivial > > > > proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a > > proof_CPS_DoubleNeg cont = cont > > > > We only specialized `r ~ Void`, which mean we can transform a `CPS > > a` > > into a `DoubleNeg a`. So far so good, we are missing the other > > implication > > > > -- bind type variables: a, r > > -- cont :: (a -> Void) -> Void > > -- absurd :: forall b. Void -> b > > -- cc :: a -> r > > proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a > > proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) > > > > Trouble, we can't fill `_missing :: r -> Void` as such function > > only > > exists when `r ~ Void` as it must be the empty function. This is > > why I > > don't think `CPS a` is the double negation. > > > > But I can see how people can get confused. Given a value `x :: a` > > we can > > embed it onto `CPS a` via `return x`. As we saw before we can pass > > from > > `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from > > `a` to > > `DoubleNeg a`, the first one is directly as in the previous mail. > > The > > second one is using `proof_CPS_DoubleNeg` > > > > embed_onto_DoubleNeg :: a -> DoubleNeg > > embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return > > where > > return :: a -> CPS a > > return a = ($ a) > > > > So CPS is /almost/ the double negation. It is still interesting > > because > > it's enough to embed a classical fragment of logic onto the > > constructive > > fragment (LEM, pierce etc). But calling it a double negation really > > tripped me off. > > > > Am I correct? Or is there other reason why CPS is called the double > > negation transformation? > > > > Thank for your time reading this, I know it was long. > > > > [1]: http://jelv.is/talks/curry-howard.html#slide30 > > [2]: > > > > https://www.quora.com/What-is-continuation-passing-style-in-functional-programming > > > > -- > > -- Rubén > > -- pgp: 4EE9 28F7 932E F4AD > > > > _______________________________________________ > > Haskell-Cafe mailing list > > To (un)subscribe, modify options or view archives go to: > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > > Only members subscribed via the mailman list are allowed to post. From lysxia at gmail.com Fri May 15 21:59:22 2020 From: lysxia at gmail.com (Li-yao Xia) Date: Fri, 15 May 2020 17:59:22 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: Hi Ruben, > I've seen > claimed on the web that the CPS transform *is* the double negation [1] > [2]. I don't think that true, it is almost true in my view. I'll > explain, these are the types at hand: > > type DoubleNeg a = (a -> Void) -> Void > type CPS a = forall r. (a -> r) -> r You're reading too much into this claim. When I read "CPS", I would think of types of the form ((a -> r) -> r), but how the r gets instantiated or quantified is very context-dependent. Note that (forall r. (a -> r) -> r) is isomorphic to a. From that, you can conclude that it is not isomorphic to ((a -> Void) -> Void). Looking at types only, the correspondence between double negation and CPS is only a superficial observation that ((a -> Void) -> Void) matches ((a -> r) -> r) simply by setting (r = Void). But CPS is a program transformation before all. Therefore, to understand the correspondence with double negation, we should really be looking at the level of terms (programs or proofs). 1. Define a language of proofs in classical logic. Below is one of many ways of doing it, notably featuring a rule for double-negation elimination (NotNot). A term (x :: K a) is a proof of the proposition a. data K a where AndI :: K a -> K b -> K (a :*: b) OrIL :: K a -> K (a :+: b) OrIR :: K b -> K (a :+: b) ImplI :: (a -> K b) -> K (a :->: b) Assumption :: a -> K a Cut :: K (a :->: b) -> K a -> K b NotNot :: K (Not (Not a)) -> K a 2. Double negation enables a translation of classical logic in intuitionistic logic, here embedded in Haskell: translate :: K a -> Not (Not a) translate (NotNot p) k = translate p \f -> f k translate (Cut pf px) k = translate pf \f -> translate px \x -> f x k {- etc. -} {- also omitted: the translation of formulas ((:*:), (:+:), (:->:), Not) which is performed implicitly in the above definition of K. -} Full gist: https://gist.github.com/Lysxia/d90afbe716163b03acf765a2e63062cd The point is that the proof language K is literally a programming language (with sums, products, first-order functions, and a weird operator given by double negation elimination), and the "translate" function is literally an interpreter in the programming sense, which one might call a "shallowly embedded compiler", where the target language is in continuation-passing style. Thus, CPS transformation and double-negation translation don't just look similar; when phrased in a certain way, they are literally the same thing. The translation is not unique. There are multiple flavors of "CPS transformation" (or "double-negation translation") depending on where exactly negations are introduced in the translation of formulas. Cheers, Li-yao On 5/15/20 5:19 AM, Ruben Astudillo wrote: > On 13-05-20 09:15, Olaf Klinke wrote: >> Excersise: Prove that intuitionistically, it is absurd to deny the law >> of excluded middle: >> >> Not (Not (Either a (Not a))) > > It took me a while but it was good effort. I will try to explain how I > derived it. We need a term for > > proof :: Not (Not (Either a (Not a))) > proof :: (Either a (Not a) -> Void) -> Void > > A first approximation is > > -- Use the (cont :: Either a (Not a) -> Void) to construct the Void > -- We need to pass it an Either a (Not a) > proof :: (Either a (Not a) -> Void) -> Void > proof cont = cont $ Left > > Damn, we can't use the `Left` constructor as we are missing an `a` value > to fill with. Let's try with `Right` > > proof :: (Either a (Not a) -> Void) -> Void > proof cont = cont $ Right (\a -> cont (Left a)) > > Mind bending. But it does make sense, on the `Right` constructor we > assume we are have an `a` but we have to return a `Void`. Luckily we can > construct a `Void` retaking the path we were gonna follow before filling > with a `Left a`. > > Along the way I had other questions related to the original mail and > given you seem knowledgeable I want to corroborate with you. I've seen > claimed on the web that the CPS transform *is* the double negation [1] > [2]. I don't think that true, it is almost true in my view. I'll > explain, these are the types at hand: > > type DoubleNeg a = (a -> Void) -> Void > type CPS a = forall r. (a -> r) -> r > > We want to see there is an equivalence/isomorphism between the two > types. One implication is trivial > > proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a > proof_CPS_DoubleNeg cont = cont > > We only specialized `r ~ Void`, which mean we can transform a `CPS a` > into a `DoubleNeg a`. So far so good, we are missing the other > implication > > -- bind type variables: a, r > -- cont :: (a -> Void) -> Void > -- absurd :: forall b. Void -> b > -- cc :: a -> r > proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a > proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) > > Trouble, we can't fill `_missing :: r -> Void` as such function only > exists when `r ~ Void` as it must be the empty function. This is why I > don't think `CPS a` is the double negation. > > But I can see how people can get confused. Given a value `x :: a` we can > embed it onto `CPS a` via `return x`. As we saw before we can pass from > `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to > `DoubleNeg a`, the first one is directly as in the previous mail. The > second one is using `proof_CPS_DoubleNeg` > > embed_onto_DoubleNeg :: a -> DoubleNeg > embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return > where > return :: a -> CPS a > return a = ($ a) > > So CPS is /almost/ the double negation. It is still interesting because > it's enough to embed a classical fragment of logic onto the constructive > fragment (LEM, pierce etc). But calling it a double negation really > tripped me off. > > Am I correct? Or is there other reason why CPS is called the double > negation transformation? > > Thank for your time reading this, I know it was long. > > [1]: http://jelv.is/talks/curry-howard.html#slide30 > [2]: > https://www.quora.com/What-is-continuation-passing-style-in-functional-programming > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > From olf at aatal-apotheke.de Sat May 16 08:41:28 2020 From: olf at aatal-apotheke.de (Olaf Klinke) Date: Sat, 16 May 2020 10:41:28 +0200 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: <4f877116d0aa3418ef40b2a2ac39b8511f48fbf2.camel@aatal-apotheke.de> As usual, Edward Kmett has the answer for anything categorical in Haskell. The type CPS a = forall r. (a -> r) -> r is isomorphic to Yoneda Identity a = forall r. (a -> r) -> Identity r and the latter is the Yoneda embedding [1] of the Identity functor. The Yoneda Lemma [2,3] states that for any functor f, the Yoneda embedding of f is isomorphic to f. We conclude that CPS a is isomorphic to a, and the relationship you found with Void is akin to the fact that in any Heyting algebra, any element is smaller than its double negation. Olaf [1] https://hackage.haskell.org/package/kan-extensions/docs/Data-Functor-Yoneda.html See also the blog post linked at the top of that page. [*] [2] https://en.wikipedia.org/wiki/Yoneda_lemma [3] https://ncatlab.org/nlab/show/Yoneda+embedding [*] Fun fact: If you install a Haskell package and watch which dependencies are build, surprisingly often kan-extensions is among them. You'd think: What the hell does category theory have to do with my program? But hey, this is a Haskell program you're writing, so you really should not be surprised. From iblech at web.de Sat May 16 12:54:00 2020 From: iblech at web.de (Ingo Blechschmidt) Date: Sat, 16 May 2020 14:54:00 +0200 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: <20200516125400.GA7901@quasicoherent.io> On Fri 15 May 2020 05:19:01 AM GMT, Ruben Astudillo wrote: > On 13-05-20 09:15, Olaf Klinke wrote: > > Excersise: Prove that intuitionistically, it is absurd to deny the law > > of excluded middle: > > > > Not (Not (Either a (Not a))) This fact is indeed truly wondrous. I encourage everyone to ponder it thoroughly. It has been worked into a classical logic fairy tale: http://blog.ezyang.com/2013/04/a-classical-logic-fairy-tale/ (sorry for http) And more in this little Oleg jewel: https://web.archive.org/web/20180901035449/http://okmij.org/ftp/Computation/lem.html > given you seem knowledgeable I want to corroborate with you. I've seen > claimed on the web that the CPS transform *is* the double negation [1] > [2]. I don't think that true, it is almost true in my view. I'll [...] Yes, you are right, and your analysis of the situation is correct. Using (_ → R) → R for some fixed statement R instead of ¬¬_ = ((_ → ⊥) → ⊥) is what's called "the R-Friedman translation applied to the double negation translation". It is what powers "Friedman's trick", a marvelous technique for extracting constructive content from classical proofs [1]. People say that you cannot escape the continuation monad. But sometimes, you can. Dickson's lemma nicely illustrates this insight. It states that for any infinite list xs ∷ [Nat], there is an index i such that xs !! i ≤ xs !! (i + 1). This lemma has a trivial classical proof (just pick the minimum of the list xs), but this classical proof is not effective: There is no algorithm for computing the minimum of an infinite list. Using the continuation monad, we can extract the constructive content of this classical proof. See here: https://github.com/iblech/talk-constructive-mathematics/blob/master/law-of-exluded-middle.hs Cheers, Ingo [1] Say you want to constructively prove A → B. You already have a classical proof of A → B, and you managed [2] to turn this proof into a constructive proof of ((A → R) → R) → ((B → R) → R), for any as of yet undecided statement R. Now specialize to R ≔ B. Hence we have a constructive proof of ((A → B) → B) → ((B → B) → B). Combining this with the constructive tautologies A → ((A → B) → B) and ((B → B) → B) ↔ B, we obtain a constructive proof of A → B. [2] A metatheorem states that if some statement A is classically provable then its double negation translation and furthermore the R-Friedman translation of the double negation translation are constructively provable. (Incidentally, this metatheorem has a constructive proof.) But "translation" here means more than just replacing A by ¬¬A (respectively ((A → R) → R)). It means introducing a double negation in front of every equality, disjunction and existential quantification. For instance, the ¬¬-translation of ∀x. ∃y. f(x,y) = g(x,y) is ∀x. ¬¬∃y. ¬¬(f(x,y) = g(x,y)). In some circumstances, the double negation translation of a complex statement A is constructively equivalent to ¬¬A, that is, in some circumstances the many nested double negations can be pulled to the front. This is for instance the case for so-called "geometric formulas", statements in which the logical symbols "→" and "∀" don't occur. From olf at aatal-apotheke.de Sat May 16 19:56:51 2020 From: olf at aatal-apotheke.de (Olaf Klinke) Date: Sat, 16 May 2020 21:56:51 +0200 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) Message-ID: <4bf3022bcf2b3a6a8b28007b8f3dba640a386225.camel@aatal-apotheke.de> > 2. Double negation enables a translation of classical logic in > intuitionistic logic, here embedded in Haskell: > Below I'll give a variant of Li-yao's logic language in Haskell98. Again, the open set model may help to visualize CPS translation: Consider all open sets A on the real line which are fixed points of double negation. All intervals are of this kind, but poking holes in them destroys this property: ---(====)(====)--- A ===)----------(=== Not A ---(==========)--- Not (Not A) Denote the collection of open sets invariant under double negation by X. As the example above demonstrates, X is not closed under set union. But set intersection preserves membership of X. So we have a funny logic that has (&&) but no (||). The CPS trick is now to define a new (||) by means of double negation: ---(====)--------- A ---------(====)--- B ---(====)(====)--- set union of A and B ---(==========)--- A || B, double negation of set union. In fact X is the largest Boolean algebra contained in the Heyting algebra of open sets. In terms of Haskell, we define a new Either: Either' a b = ((Either a b) -> Void) -> Void Looks familiar? Indeed, in this thread we already proved Either' a (Not a). This says that Not A is the Boolean complement of A in X. Using (,) and Either' for (&&) and (||) you can realize all proofs of classical propositional logic in Haskell without GADTs. Olaf From zhujinxuan at gmail.com Sun May 17 07:47:06 2020 From: zhujinxuan at gmail.com (Jinxuan Zhu) Date: Sun, 17 May 2020 03:47:06 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: <4bf3022bcf2b3a6a8b28007b8f3dba640a386225.camel@aatal-apotheke.de> References: <4bf3022bcf2b3a6a8b28007b8f3dba640a386225.camel@aatal-apotheke.de> Message-ID: Just want to post some other things if someone is interested about using Yoneda. Because Void -> a is unique, (Yo void) is terminal in [C, Set]. We can convert the (a -> void) -> (b -> void) as Yo a ~> Yo b. Some details are attached. On Sat, May 16, 2020, 3:58 PM Olaf Klinke wrote: > > 2. Double negation enables a translation of classical logic in > > intuitionistic logic, here embedded in Haskell: > > > Below I'll give a variant of Li-yao's logic language in Haskell98. > Again, the open set model may help to visualize CPS translation: > > Consider all open sets A on the real line which are fixed points of > double negation. All intervals are of this kind, but poking holes in > them destroys this property: > > ---(====)(====)--- A > ===)----------(=== Not A > ---(==========)--- Not (Not A) > > Denote the collection of open sets invariant under double negation by > X. As the example above demonstrates, X is not closed under set union. > But set intersection preserves membership of X. So we have a funny > logic that has (&&) but no (||). The CPS trick is now to define a new > (||) by means of double negation: > > ---(====)--------- A > ---------(====)--- B > ---(====)(====)--- set union of A and B > ---(==========)--- A || B, double negation of set union. > > In fact X is the largest Boolean algebra contained in the Heyting > algebra of open sets. In terms of Haskell, we define a new Either: > > Either' a b = ((Either a b) -> Void) -> Void > > Looks familiar? Indeed, in this thread we already proved > > Either' a (Not a). > > This says that Not A is the Boolean complement of A in X. Using (,) and > Either' for (&&) and (||) you can realize all proofs of classical > propositional logic in Haskell without GADTs. > > Olaf > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: IMG_20200517_033939.jpg Type: image/jpeg Size: 4424494 bytes Desc: not available URL: From ky3 at atamo.com Mon May 18 01:00:00 2020 From: ky3 at atamo.com (Kim-Ee Yeoh) Date: Mon, 18 May 2020 08:00:00 +0700 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: Very cool to see the constructive code for the proof of double negation in intuitionistic logic. But what about the Curry-Howard correspondence for classical logic? What would the classical code for the classical proof of excluded middle look like? On Fri, May 15, 2020 at 11:09 PM Chris Smith wrote: > This was indeed a fun puzzle to play with. I think this becomes easier to > interpret if you factor out De Morgan's Law from the form you posted at the > beginning of your email. > > https://code.world/haskell#PYGDwpaMZ_2iSs74NnwCUrg > > > On Fri, May 15, 2020 at 5:23 AM Ruben Astudillo > wrote: > >> On 13-05-20 09:15, Olaf Klinke wrote: >> > Excersise: Prove that intuitionistically, it is absurd to deny the law >> > of excluded middle: >> > >> > Not (Not (Either a (Not a))) >> >> It took me a while but it was good effort. I will try to explain how I >> derived it. We need a term for >> >> proof :: Not (Not (Either a (Not a))) >> proof :: (Either a (Not a) -> Void) -> Void >> >> A first approximation is >> >> -- Use the (cont :: Either a (Not a) -> Void) to construct the Void >> -- We need to pass it an Either a (Not a) >> proof :: (Either a (Not a) -> Void) -> Void >> proof cont = cont $ Left >> >> Damn, we can't use the `Left` constructor as we are missing an `a` value >> to fill with. Let's try with `Right` >> >> proof :: (Either a (Not a) -> Void) -> Void >> proof cont = cont $ Right (\a -> cont (Left a)) >> >> Mind bending. But it does make sense, on the `Right` constructor we >> assume we are have an `a` but we have to return a `Void`. Luckily we can >> construct a `Void` retaking the path we were gonna follow before filling >> with a `Left a`. >> >> Along the way I had other questions related to the original mail and >> given you seem knowledgeable I want to corroborate with you. I've seen >> claimed on the web that the CPS transform *is* the double negation [1] >> [2]. I don't think that true, it is almost true in my view. I'll >> explain, these are the types at hand: >> >> type DoubleNeg a = (a -> Void) -> Void >> type CPS a = forall r. (a -> r) -> r >> >> We want to see there is an equivalence/isomorphism between the two >> types. One implication is trivial >> >> proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a >> proof_CPS_DoubleNeg cont = cont >> >> We only specialized `r ~ Void`, which mean we can transform a `CPS a` >> into a `DoubleNeg a`. So far so good, we are missing the other >> implication >> >> -- bind type variables: a, r >> -- cont :: (a -> Void) -> Void >> -- absurd :: forall b. Void -> b >> -- cc :: a -> r >> proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a >> proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) >> >> Trouble, we can't fill `_missing :: r -> Void` as such function only >> exists when `r ~ Void` as it must be the empty function. This is why I >> don't think `CPS a` is the double negation. >> >> But I can see how people can get confused. Given a value `x :: a` we can >> embed it onto `CPS a` via `return x`. As we saw before we can pass from >> `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to >> `DoubleNeg a`, the first one is directly as in the previous mail. The >> second one is using `proof_CPS_DoubleNeg` >> >> embed_onto_DoubleNeg :: a -> DoubleNeg >> embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return >> where >> return :: a -> CPS a >> return a = ($ a) >> >> So CPS is /almost/ the double negation. It is still interesting because >> it's enough to embed a classical fragment of logic onto the constructive >> fragment (LEM, pierce etc). But calling it a double negation really >> tripped me off. >> >> Am I correct? Or is there other reason why CPS is called the double >> negation transformation? >> >> Thank for your time reading this, I know it was long. >> >> [1]: http://jelv.is/talks/curry-howard.html#slide30 >> [2]: >> >> https://www.quora.com/What-is-continuation-passing-style-in-functional-programming >> >> -- >> -- Rubén >> -- pgp: 4EE9 28F7 932E F4AD >> >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -- -- Kim-Ee -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Mon May 18 01:19:33 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 17 May 2020 21:19:33 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: Classically, the excluded middle is an axiom, not a theorem. There is no code/proof. On Sun, May 17, 2020, 9:02 PM Kim-Ee Yeoh wrote: > Very cool to see the constructive code for the proof of double negation in > intuitionistic logic. > > > But what about the Curry-Howard correspondence for classical logic? > > > What would the classical code for the classical proof of excluded middle > look like? > > On Fri, May 15, 2020 at 11:09 PM Chris Smith wrote: > >> This was indeed a fun puzzle to play with. I think this becomes easier >> to interpret if you factor out De Morgan's Law from the form you posted at >> the beginning of your email. >> >> https://code.world/haskell#PYGDwpaMZ_2iSs74NnwCUrg >> >> >> On Fri, May 15, 2020 at 5:23 AM Ruben Astudillo >> wrote: >> >>> On 13-05-20 09:15, Olaf Klinke wrote: >>> > Excersise: Prove that intuitionistically, it is absurd to deny the law >>> > of excluded middle: >>> > >>> > Not (Not (Either a (Not a))) >>> >>> It took me a while but it was good effort. I will try to explain how I >>> derived it. We need a term for >>> >>> proof :: Not (Not (Either a (Not a))) >>> proof :: (Either a (Not a) -> Void) -> Void >>> >>> A first approximation is >>> >>> -- Use the (cont :: Either a (Not a) -> Void) to construct the Void >>> -- We need to pass it an Either a (Not a) >>> proof :: (Either a (Not a) -> Void) -> Void >>> proof cont = cont $ Left >>> >>> Damn, we can't use the `Left` constructor as we are missing an `a` value >>> to fill with. Let's try with `Right` >>> >>> proof :: (Either a (Not a) -> Void) -> Void >>> proof cont = cont $ Right (\a -> cont (Left a)) >>> >>> Mind bending. But it does make sense, on the `Right` constructor we >>> assume we are have an `a` but we have to return a `Void`. Luckily we can >>> construct a `Void` retaking the path we were gonna follow before filling >>> with a `Left a`. >>> >>> Along the way I had other questions related to the original mail and >>> given you seem knowledgeable I want to corroborate with you. I've seen >>> claimed on the web that the CPS transform *is* the double negation [1] >>> [2]. I don't think that true, it is almost true in my view. I'll >>> explain, these are the types at hand: >>> >>> type DoubleNeg a = (a -> Void) -> Void >>> type CPS a = forall r. (a -> r) -> r >>> >>> We want to see there is an equivalence/isomorphism between the two >>> types. One implication is trivial >>> >>> proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a >>> proof_CPS_DoubleNeg cont = cont >>> >>> We only specialized `r ~ Void`, which mean we can transform a `CPS a` >>> into a `DoubleNeg a`. So far so good, we are missing the other >>> implication >>> >>> -- bind type variables: a, r >>> -- cont :: (a -> Void) -> Void >>> -- absurd :: forall b. Void -> b >>> -- cc :: a -> r >>> proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a >>> proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) >>> >>> Trouble, we can't fill `_missing :: r -> Void` as such function only >>> exists when `r ~ Void` as it must be the empty function. This is why I >>> don't think `CPS a` is the double negation. >>> >>> But I can see how people can get confused. Given a value `x :: a` we can >>> embed it onto `CPS a` via `return x`. As we saw before we can pass from >>> `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to >>> `DoubleNeg a`, the first one is directly as in the previous mail. The >>> second one is using `proof_CPS_DoubleNeg` >>> >>> embed_onto_DoubleNeg :: a -> DoubleNeg >>> embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return >>> where >>> return :: a -> CPS a >>> return a = ($ a) >>> >>> So CPS is /almost/ the double negation. It is still interesting because >>> it's enough to embed a classical fragment of logic onto the constructive >>> fragment (LEM, pierce etc). But calling it a double negation really >>> tripped me off. >>> >>> Am I correct? Or is there other reason why CPS is called the double >>> negation transformation? >>> >>> Thank for your time reading this, I know it was long. >>> >>> [1]: http://jelv.is/talks/curry-howard.html#slide30 >>> [2]: >>> >>> https://www.quora.com/What-is-continuation-passing-style-in-functional-programming >>> >>> -- >>> -- Rubén >>> -- pgp: 4EE9 28F7 932E F4AD >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> To (un)subscribe, modify options or view archives go to: >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> Only members subscribed via the mailman list are allowed to post. >> >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. > > -- > -- Kim-Ee > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ruben.astud at gmail.com Mon May 18 03:05:38 2020 From: ruben.astud at gmail.com (Ruben Astudillo) Date: Sun, 17 May 2020 23:05:38 -0400 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: On 17-05-20 21:00, Kim-Ee Yeoh wrote: > But what about the Curry-Howard correspondence for classical logic? Curry-Howard only offers a translation between a fragment of logic that is constructive logic and the typed lambda calculus. But that is not the whole story, we can embed classical logic into constructive logic via the the "double negation translation" [1]. How is such thing possible? The idea is that classical logic is constructive logic with an extra axiom. That extra axiom can either be Pierce's Law, the excluded middle or the double negation elimination. Which ever you "add" to your constructive logic will make it a classical logic. Here is the trick, to whatever proposition `a` that we want to prove, we can "add" an extra postulate for a non-local jump as an argument and call that proposition `CPS a`. That way, when proving/constructing the term inside the CPS-code, you will have at your hand an extra argument that will allow you to fill the extra power needed by classical proofs [1]. It's interesting to note that operationally, what classical proofs can do that constructive proofs cannot is the ability to do non-local jumps, there represented by the continuation. Harper's course given at [2] has been my fun the last few days and explains it in greater detail. > What would the classical code for the classical proof of excluded middle > look like? As in the previous mails type Not a = a -> Void type CPS a = (a -> Void) -> Void proof :: CPS (Either a (Not a)) proof = \cont -> cont $ Right (\a -> cont (Left a)) Modulo my point between the different representations of CPS and their relation to the double negation, that code only type check because terms under CPS have access to an extra non-local jump to allow classical arguments. Even so this code is *good* as shows explicitly when the non-local jumps happen and the rest of the code is constructive. [1]: https://www.cs.cmu.edu/~rwh/courses/clogic/www/handouts/class.pdf [2]: https://www.cs.cmu.edu/~rwh/courses/clogic/www/handouts -- -- Rubén -- pgp: 4EE9 28F7 932E F4AD -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From kazu at iij.ad.jp Mon May 18 03:56:47 2020 From: kazu at iij.ad.jp (Kazu Yamamoto (=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=)) Date: Mon, 18 May 2020 12:56:47 +0900 (JST) Subject: [Haskell-cafe] tuple and pattern synonym Message-ID: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> Hi, I have a question about PatternSynonyms. Suppose we have: data Foo = Foo Int Int I would like to define a pattern as follows: pattern P :: (Int,Int) -> Foo pattern P (x,y) = Foo x y But this results in "parse error on input ‘(’". Are there any ways to use tuple in the left side hand of patterns? This is important to maintain backward compatibility for the "network" library. If there is no way, I will define Foo as: data Foo = Foo (Int,Int) -- awkward and define P as: pattern P :: (Int,Int) -> Foo pattern P xy = Foo xy Regards, --Kazu From david.feuer at gmail.com Mon May 18 04:14:06 2020 From: david.feuer at gmail.com (David Feuer) Date: Mon, 18 May 2020 00:14:06 -0400 Subject: [Haskell-cafe] tuple and pattern synonym In-Reply-To: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> References: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> Message-ID: You need to use a view pattern with an explicitly bidirectional pattern synonym: pattern P :: (Int,Int) -> Foo pattern P xy <- ((\(Foo x y) -> (x, y)) -> xy) where P (x, y) = Foo x y If the Foo type had more than one constructor, then you'd need to do something a bit trickier, like pattern P xy <- ((\case Foo x y -> Just (x, y) _ -> Nothing) -> Just xy) where P (x, y) = Foo x y On Sun, May 17, 2020, 11:57 PM Kazu Yamamoto wrote: > Hi, > > I have a question about PatternSynonyms. Suppose we have: > > data Foo = Foo Int Int > > I would like to define a pattern as follows: > > pattern P :: (Int,Int) -> Foo > pattern P (x,y) = Foo x y > > But this results in "parse error on input ‘(’". Are there any ways to > use tuple in the left side hand of patterns? > > This is important to maintain backward compatibility for the "network" > library. > > If there is no way, I will define Foo as: > > data Foo = Foo (Int,Int) -- awkward > > and define P as: > > pattern P :: (Int,Int) -> Foo > pattern P xy = Foo xy > > Regards, > > --Kazu > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. lol -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Mon May 18 04:18:20 2020 From: david.feuer at gmail.com (David Feuer) Date: Mon, 18 May 2020 00:18:20 -0400 Subject: [Haskell-cafe] tuple and pattern synonym In-Reply-To: References: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> Message-ID: By the way, I personally don't consider the syntax you need to use here remotely obvious. I really wish we had something more intuitive for defining these sorts of patterns! On Mon, May 18, 2020, 12:14 AM David Feuer wrote: > You need to use a view pattern with an explicitly bidirectional pattern > synonym: > > pattern P :: (Int,Int) -> Foo > pattern P xy <- ((\(Foo x y) -> (x, y)) -> xy) > where > P (x, y) = Foo x y > > If the Foo type had more than one constructor, then you'd need to do > something a bit trickier, like > > pattern P xy <- ((\case > Foo x y -> Just (x, y) > _ -> Nothing) -> Just xy) > where > P (x, y) = Foo x y > > On Sun, May 17, 2020, 11:57 PM Kazu Yamamoto wrote: > >> Hi, >> >> I have a question about PatternSynonyms. Suppose we have: >> >> data Foo = Foo Int Int >> >> I would like to define a pattern as follows: >> >> pattern P :: (Int,Int) -> Foo >> pattern P (x,y) = Foo x y >> >> But this results in "parse error on input ‘(’". Are there any ways to >> use tuple in the left side hand of patterns? >> >> This is important to maintain backward compatibility for the "network" >> library. >> >> If there is no way, I will define Foo as: >> >> data Foo = Foo (Int,Int) -- awkward >> >> and define P as: >> >> pattern P :: (Int,Int) -> Foo >> pattern P xy = Foo xy >> >> Regards, >> >> --Kazu >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. lol > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kazu at iij.ad.jp Mon May 18 06:29:34 2020 From: kazu at iij.ad.jp (Kazu Yamamoto (=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=)) Date: Mon, 18 May 2020 15:29:34 +0900 (JST) Subject: [Haskell-cafe] tuple and pattern synonym In-Reply-To: References: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> Message-ID: <20200518.152934.1454101781667568220.kazu@iij.ad.jp> Hi David, > You need to use a view pattern with an explicitly bidirectional pattern > synonym: > > pattern P :: (Int,Int) -> Foo > pattern P xy <- ((\(Foo x y) -> (x, y)) -> xy) > where > P (x, y) = Foo x y Great! To maintain backward compatibility of the "network" library, I have created a PR: https://github.com/haskell/network/pull/455 Thank you for your suggestion! --Kazu From ky3 at atamo.com Mon May 18 07:52:23 2020 From: ky3 at atamo.com (Kim-Ee Yeoh) Date: Mon, 18 May 2020 14:52:23 +0700 Subject: [Haskell-cafe] Relationship between ((a -> Void) -> Void) and (forall r. (a -> r) -> r) In-Reply-To: References: <9b962c6c99038a4930b4970c5abbcfc6cb271c4f.camel@aatal-apotheke.de> Message-ID: On Mon, May 18, 2020 at 8:19 AM David Feuer wrote: > Classically, the excluded middle is an axiom, not a theorem. > Untrue in general. > On Sun, May 17, 2020, 9:02 PM Kim-Ee Yeoh wrote: > >> Very cool to see the constructive code for the proof of double negation >> in intuitionistic logic. >> >> >> But what about the Curry-Howard correspondence for classical logic? >> >> >> What would the classical code for the classical proof of excluded middle >> look like? >> >> On Fri, May 15, 2020 at 11:09 PM Chris Smith wrote: >> >>> This was indeed a fun puzzle to play with. I think this becomes easier >>> to interpret if you factor out De Morgan's Law from the form you posted at >>> the beginning of your email. >>> >>> https://code.world/haskell#PYGDwpaMZ_2iSs74NnwCUrg >>> >>> >>> On Fri, May 15, 2020 at 5:23 AM Ruben Astudillo >>> wrote: >>> >>>> On 13-05-20 09:15, Olaf Klinke wrote: >>>> > Excersise: Prove that intuitionistically, it is absurd to deny the law >>>> > of excluded middle: >>>> > >>>> > Not (Not (Either a (Not a))) >>>> >>>> It took me a while but it was good effort. I will try to explain how I >>>> derived it. We need a term for >>>> >>>> proof :: Not (Not (Either a (Not a))) >>>> proof :: (Either a (Not a) -> Void) -> Void >>>> >>>> A first approximation is >>>> >>>> -- Use the (cont :: Either a (Not a) -> Void) to construct the Void >>>> -- We need to pass it an Either a (Not a) >>>> proof :: (Either a (Not a) -> Void) -> Void >>>> proof cont = cont $ Left >>>> >>>> Damn, we can't use the `Left` constructor as we are missing an `a` value >>>> to fill with. Let's try with `Right` >>>> >>>> proof :: (Either a (Not a) -> Void) -> Void >>>> proof cont = cont $ Right (\a -> cont (Left a)) >>>> >>>> Mind bending. But it does make sense, on the `Right` constructor we >>>> assume we are have an `a` but we have to return a `Void`. Luckily we can >>>> construct a `Void` retaking the path we were gonna follow before filling >>>> with a `Left a`. >>>> >>>> Along the way I had other questions related to the original mail and >>>> given you seem knowledgeable I want to corroborate with you. I've seen >>>> claimed on the web that the CPS transform *is* the double negation [1] >>>> [2]. I don't think that true, it is almost true in my view. I'll >>>> explain, these are the types at hand: >>>> >>>> type DoubleNeg a = (a -> Void) -> Void >>>> type CPS a = forall r. (a -> r) -> r >>>> >>>> We want to see there is an equivalence/isomorphism between the two >>>> types. One implication is trivial >>>> >>>> proof_CPS_DoubleNeg :: forall a. CPS a -> DoubleNeg a >>>> proof_CPS_DoubleNeg cont = cont >>>> >>>> We only specialized `r ~ Void`, which mean we can transform a `CPS a` >>>> into a `DoubleNeg a`. So far so good, we are missing the other >>>> implication >>>> >>>> -- bind type variables: a, r >>>> -- cont :: (a -> Void) -> Void >>>> -- absurd :: forall b. Void -> b >>>> -- cc :: a -> r >>>> proof_DoubleNeg_CPS :: forall a. DoubleNeg a -> CPS a >>>> proof_DoubleNeg_CPS cont = \cc -> absurd $ cont (_missing . cc) >>>> >>>> Trouble, we can't fill `_missing :: r -> Void` as such function only >>>> exists when `r ~ Void` as it must be the empty function. This is why I >>>> don't think `CPS a` is the double negation. >>>> >>>> But I can see how people can get confused. Given a value `x :: a` we can >>>> embed it onto `CPS a` via `return x`. As we saw before we can pass from >>>> `CPS a` to `DoubleNeg a`. So we have *two* ways for passing from `a` to >>>> `DoubleNeg a`, the first one is directly as in the previous mail. The >>>> second one is using `proof_CPS_DoubleNeg` >>>> >>>> embed_onto_DoubleNeg :: a -> DoubleNeg >>>> embed_onto_DoubleNeg = proof_CPS_DoubleNeg . return >>>> where >>>> return :: a -> CPS a >>>> return a = ($ a) >>>> >>>> So CPS is /almost/ the double negation. It is still interesting because >>>> it's enough to embed a classical fragment of logic onto the constructive >>>> fragment (LEM, pierce etc). But calling it a double negation really >>>> tripped me off. >>>> >>>> Am I correct? Or is there other reason why CPS is called the double >>>> negation transformation? >>>> >>>> Thank for your time reading this, I know it was long. >>>> >>>> [1]: http://jelv.is/talks/curry-howard.html#slide30 >>>> [2]: >>>> >>>> https://www.quora.com/What-is-continuation-passing-style-in-functional-programming >>>> >>>> -- >>>> -- Rubén >>>> -- pgp: 4EE9 28F7 932E F4AD >>>> >>>> _______________________________________________ >>>> Haskell-Cafe mailing list >>>> To (un)subscribe, modify options or view archives go to: >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>>> Only members subscribed via the mailman list are allowed to post. >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> To (un)subscribe, modify options or view archives go to: >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> Only members subscribed via the mailman list are allowed to post. >> >> -- >> -- Kim-Ee >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. > > -- -- Kim-Ee -------------- next part -------------- An HTML attachment was scrubbed... URL: From rae at richarde.dev Mon May 18 08:31:15 2020 From: rae at richarde.dev (Richard Eisenberg) Date: Mon, 18 May 2020 09:31:15 +0100 Subject: [Haskell-cafe] tuple and pattern synonym In-Reply-To: References: <20200518.125647.1792303905811307304.kazu@iij.ad.jp> Message-ID: <3E36B679-3447-43D2-9B98-9FFD67A1E76D@richarde.dev> > On May 18, 2020, at 5:18 AM, David Feuer wrote: > > By the way, I personally don't consider the syntax you need to use here remotely obvious. I really wish we had something more intuitive for defining these sorts of patterns! Would https://github.com/ghc-proposals/ghc-proposals/pull/138 satisfy this wish? I remember really liking this proposal when it appeared, but I never put the time into seeing it through. Richard From ben at well-typed.com Mon May 18 22:20:33 2020 From: ben at well-typed.com (Ben Gamari) Date: Mon, 18 May 2020 18:20:33 -0400 Subject: [Haskell-cafe] [HIW'20] Second Call for Talks Message-ID: <87zha4yjf9.fsf@smart-cactus.org> Hello everyone, Haskell Implementors Workshop is calling for talk proposals. Co-located with ICFP, HiW is an ideal place to describe a Haskell library, a Haskell extension, compiler, works-in-progress, demo a new Haskell-related tool, or even propose future lines of Haskell development. The deadline for submissions is July 2nd 2020. Call for Talks ============== The 12th Haskell Implementors’ Workshop is to be held alongside ICFP 2020 this year. It is a forum for people involved in the design and development of Haskell implementations, tools, libraries, and supporting infrastructure, to share their work and discuss future directions and collaborations with others. Talks and/or demos are proposed by submitting an abstract, and selected by a small program committee. There will be no published proceedings. The workshop will be informal and interactive, with open spaces in the timetable and room for ad-hoc discussion, demos and lightning talks. Scope and Target Audience ------------------------- It is important to distinguish the Haskell Implementors’ Workshop from the Haskell Symposium which is also co-located with ICFP 2020. The Haskell Symposium is for the publication of Haskell-related research. In contrast, the Haskell Implementors’ Workshop will have no proceedings – although we will aim to make talk videos, slides and presented data available with the consent of the speakers. The Implementors’ Workshop is an ideal place to describe a Haskell extension, describe works-in-progress, demo a new Haskell-related tool, or even propose future lines of Haskell development. Members of the wider Haskell community encouraged to attend the workshop – we need your feedback to keep the Haskell ecosystem thriving. Students working with Haskell are specially encouraged to share their work. The scope covers any of the following topics. There may be some topics that people feel we’ve missed, so by all means submit a proposal even if it doesn’t fit exactly into one of these buckets: - Compilation techniques - Language features and extensions - Type system implementation - Concurrency and parallelism: language design and implementation - Performance, optimization and benchmarking - Virtual machines and run-time systems - Libraries and tools for development or deployment Talks ----- We invite proposals from potential speakers for talks and demonstrations. We are aiming for 20-minute talks with 5 minutes for questions and changeovers. We want to hear from people writing compilers, tools, or libraries, people with cool ideas for directions in which we should take the platform, proposals for new features to be implemented, and half-baked crazy ideas. Please submit a talk title and abstract of no more than 300 words. Submissions can be made via HotCRP at https://icfp-hiw20.hotcrp.com/ until July 2nd (anywhere on earth). We will also have lightning talks session. These have been very well received in recent years, and we aim to increase the time available to them. Lightning talks be ~7mins and are scheduled on the day of the workshop. Suggested topics for lightning talks are to present a single idea, a work-in-progress project, a problem to intrigue and perplex Haskell implementors, or simply to ask for feedback and collaborators. Logistics --------- Due to the on-going COVID-19 situation, ICFP (and, consequently, HIW) will be held remotely this year. However, the organizers are still working hard to provide for a great workshop experience. While we are sad that this year will lack the robust hallway track that is often the highlight of HIW, we believe that this remote workshop presents a unique opportunity to include more of the Haskell community in our discussion and explore new modes of communicating with our colleagues. We hope that you will join us in making this HIW as vibrant as any other. Program Committee ----------------- - Andrey Mokhov (Newcastle University) - Ben Gamari (Well-Typed LLP) - Christian Baaij (QBayLogic) - George Karachalias (Tweag I/O) - Klara Marntirosian (KU Leuven) - Matthew Pickering (Univeristy of Bristol) - Ryan G.L. Scott (Indiana University Bloomington) Best wishes, ~ Ben -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: not available URL: From komendantskaya at gmail.com Tue May 19 13:58:42 2020 From: komendantskaya at gmail.com (Ekaterina Komendantskaya) Date: Tue, 19 May 2020 14:58:42 +0100 Subject: [Haskell-cafe] Workshop on Logic Programming: Trends, Extensions, Applications, 28-29 May 2020 Message-ID: We invite participants to the on-line workshop on * Trends, Extensions, Applications and Semantics of Logic Programming* Logic programming is a framework for expressing programs, propositions and relations as Horn clause theories, and for automatic inference in these theories. Horn clause theories are famous for their well-understood declarative semantics, in which models of logic programs are given inductively or coinductively. At the same time, Horn clauses give rise to efficient inference procedures, usually involving resolution. Logic programming found applications in type inference, verification, and AI. While logic programming was originally conceived for describing simple propositional facts, it was extended to account for much more complex theories. This includes first-order theories, higher-order theories, inductive and coinductive data, and stochastic/probabilistic theories. The aim of this workshop is to bring together researchers that work on extensions of logic programming and inference methods, and to foster an exchange of methods and applications that have emerged in different communities. Keynote talk: *Dale Miller*. Structural Proof-Theory and Logic Programming Invited tutorial: *Uli Sattler*.* Description Logics and Ontology Languages - an introduction and overview* In light of COVID-19, we organise TEASE-LP as a virtual workshop and online-only event. To achieve broad participation, we use three different mediums: Discussion Forum, Pre-recorded lightning talks, Live sessions with invited and contributed live talks. Further details can be found here: https://www.coalg.org/tease-lp/workshop-schedule/. Registration is free, but we require all participants to register at https://teaselp.flarum.cloud/ For any further queries, please contact the organisers: Henning Basold Katya Komendantskaya -------------- next part -------------- An HTML attachment was scrubbed... URL: From frederic-emmanuel.picca at synchrotron-soleil.fr Wed May 20 06:23:31 2020 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Wed, 20 May 2020 06:23:31 +0000 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam Message-ID: Hello, I am writing a software which do some data treatement from hdf5 files. In order to access the data which are stored in arrays, I need to open and closes ressources. This is the purpose of the withHdf5PathP function. given a file f and a UhvPath I end up with this withUhvPathP :: (MonadSafe m, Location l) => l -> UhvPath -> ((Int -> IO Geometry) -> m r) -> m r withUhvPathP f (UhvPath m o d g w) gg = withHdf5PathP f m $ \m' -> withHdf5PathP f o $ \o' -> withHdf5PathP f d $ \d'-> withHdf5PathP f g $ \g' -> withHdf5PathP f w $ \w' -> gg (\j -> do mu <- get_position m' j omega <- get_position o' j delta <- get_position d' j gamma' <- get_position g' j wavelength <- getValueWithUnit w' 0 angstrom let positions = Data.Vector.Storable.fromList [mu, omega, delta, gamma'] let source = Source wavelength pure $ Geometry Uhv source positions Nothing) then I use this like this forever $ do (Chunk fp from to) <- await withFileP (openH5 fp) $ \f -> withHdf5PathP f imgs $ \dimgs -> withUhvPathP f dif $ \getDiffractometer -> withSamplePathP f samp $ \getSample -> forM_ [from..to-1] (\j -> yield =<< liftIO (DataFrameHkl <$> pure j <*> get_image' det dimgs j <*> getDiffractometer j <*> getSample j)) so once I open the resources, I use the getDiffratometer ((Int -> IO Geometry) -> m r) function give the position on the stream and it return the value at the j position. the purpose of this is to open the ressources only once at the begining and then send the values in a Pipe via the yield function of pipes package. I hope, I was clear. 1) I find the withUhvPathP sort of ugly, and I would like to know if it could be written more elegantly, because I will need to write a lot's of these function for different types. 2) It is the right way to design a solution to my problem (open ressources and send each values into a stream). thanks for you attention. Frederic From compl.yue at gmail.com Wed May 20 10:23:44 2020 From: compl.yue at gmail.com (Compl Yue) Date: Wed, 20 May 2020 18:23:44 +0800 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam In-Reply-To: References: Message-ID: Maybe fork another thread, keep reading data and putting into a shared `MVar` / `TMVar`, then current thread keep taking from that var? > On 2020-05-20, at 14:23, PICCA Frederic-Emmanuel wrote: > > Hello, I am writing a software which do some data treatement from hdf5 files. > > In order to access the data which are stored in arrays, I need to open and closes ressources. > This is the purpose of the withHdf5PathP function. > > given a file f and a UhvPath I end up with this > > withUhvPathP :: (MonadSafe m, Location l) => l -> UhvPath -> ((Int -> IO Geometry) -> m r) -> m r > withUhvPathP f (UhvPath m o d g w) gg = > withHdf5PathP f m $ \m' -> > withHdf5PathP f o $ \o' -> > withHdf5PathP f d $ \d'-> > withHdf5PathP f g $ \g' -> > withHdf5PathP f w $ \w' -> gg (\j -> do > mu <- get_position m' j > omega <- get_position o' j > delta <- get_position d' j > gamma' <- get_position g' j > wavelength <- getValueWithUnit w' 0 angstrom > let positions = Data.Vector.Storable.fromList [mu, omega, delta, gamma'] > let source = Source wavelength > pure $ Geometry Uhv source positions Nothing) > > > then I use this like this > > forever $ do > (Chunk fp from to) <- await > withFileP (openH5 fp) $ \f -> > withHdf5PathP f imgs $ \dimgs -> > withUhvPathP f dif $ \getDiffractometer -> > withSamplePathP f samp $ \getSample -> > forM_ [from..to-1] (\j -> yield =<< liftIO > (DataFrameHkl > <$> pure j > <*> get_image' det dimgs j > <*> getDiffractometer j > <*> getSample j)) > > so once I open the resources, I use the getDiffratometer ((Int -> IO Geometry) -> m r) function give the position on the stream and it return the value at the j position. > the purpose of this is to open the ressources only once at the begining and then send the values in a Pipe via the yield function of pipes package. > > I hope, I was clear. > > 1) I find the withUhvPathP sort of ugly, and I would like to know if it could be written more elegantly, because I will need to write a lot's of these function for different types. > > 2) It is the right way to design a solution to my problem (open ressources and send each values into a stream). > > thanks for you attention. > > Frederic > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. From joshchia at gmail.com Thu May 21 01:12:14 2020 From: joshchia at gmail.com (=?UTF-8?B?4piCSm9zaCBDaGlhICjorJ3ku7vkuK0p?=) Date: Thu, 21 May 2020 09:12:14 +0800 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam In-Reply-To: References: Message-ID: Do you mean it's ugly because of the nested withHdf4PathP? If so, have you considered ResourceT? But I saw something else that seems more noteworthy. Why is withUhvPathP being used to repeatedly open and close the same files using the filenames contained in dif? (I suppose withHdf5PathP opens and closes HDF5 files.) Why don't you open the files once in the beginning of your loop and close them at the end? You can do this by wrapping everything in a ResourceT and use allocate. On Wed, May 20, 2020 at 6:25 PM Compl Yue wrote: > Maybe fork another thread, keep reading data and putting into a shared > `MVar` / `TMVar`, then current thread keep taking from that var? > > > On 2020-05-20, at 14:23, PICCA Frederic-Emmanuel < > frederic-emmanuel.picca at synchrotron-soleil.fr> wrote: > > > > Hello, I am writing a software which do some data treatement from hdf5 > files. > > > > In order to access the data which are stored in arrays, I need to open > and closes ressources. > > This is the purpose of the withHdf5PathP function. > > > > given a file f and a UhvPath I end up with this > > > > withUhvPathP :: (MonadSafe m, Location l) => l -> UhvPath -> ((Int -> IO > Geometry) -> m r) -> m r > > withUhvPathP f (UhvPath m o d g w) gg = > > withHdf5PathP f m $ \m' -> > > withHdf5PathP f o $ \o' -> > > withHdf5PathP f d $ \d'-> > > withHdf5PathP f g $ \g' -> > > withHdf5PathP f w $ \w' -> gg (\j -> do > > mu <- get_position m' j > > omega <- get_position o' j > > delta <- get_position d' j > > gamma' <- get_position g' j > > wavelength <- getValueWithUnit w' 0 > angstrom > > let positions = > Data.Vector.Storable.fromList [mu, omega, delta, gamma'] > > let source = Source wavelength > > pure $ Geometry Uhv source > positions Nothing) > > > > > > then I use this like this > > > > forever $ do > > (Chunk fp from to) <- await > > withFileP (openH5 fp) $ \f -> > > withHdf5PathP f imgs $ \dimgs -> > > withUhvPathP f dif $ \getDiffractometer -> > > withSamplePathP f samp $ \getSample -> > > forM_ [from..to-1] (\j -> yield =<< liftIO > > (DataFrameHkl > > <$> pure j > > <*> get_image' det dimgs j > > <*> getDiffractometer j > > <*> getSample j)) > > > > so once I open the resources, I use the getDiffratometer ((Int -> IO > Geometry) -> m r) function give the position on the stream and it return > the value at the j position. > > the purpose of this is to open the ressources only once at the begining > and then send the values in a Pipe via the yield function of pipes package. > > > > I hope, I was clear. > > > > 1) I find the withUhvPathP sort of ugly, and I would like to know if it > could be written more elegantly, because I will need to write a lot's of > these function for different types. > > > > 2) It is the right way to design a solution to my problem (open > ressources and send each values into a stream). > > > > thanks for you attention. > > > > Frederic > > _______________________________________________ > > Haskell-Cafe mailing list > > To (un)subscribe, modify options or view archives go to: > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > > Only members subscribed via the mailman list are allowed to post. > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From frederic-emmanuel.picca at synchrotron-soleil.fr Thu May 21 06:59:23 2020 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Thu, 21 May 2020 06:59:23 +0000 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam In-Reply-To: References: , Message-ID: > Maybe fork another thread, keep reading data and putting into a shared `MVar` / `TMVar`, then current thread keep taking from that var? The code already use async in order to read only a chunk of the data. But is true, that I could have a thread whcih read the data and post the messag into a queue. then workers take these frames and produce a monoid. then all monoid are reduced into the final one. From frederic-emmanuel.picca at synchrotron-soleil.fr Thu May 21 07:03:36 2020 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Thu, 21 May 2020 07:03:36 +0000 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam In-Reply-To: References: , Message-ID: > Do you mean it's ugly because of the nested withHdf4PathP? If so, have you considered ResourceT? This is more about the complex signature of the function. > But I saw something else that seems more noteworthy. Why is withUhvPathP being used to repeatedly open and close the same files using the filenames contained in dif? (I suppose withHdf5PathP opens and closes HDF5 files.) Why don't you open the > files once in the beginning of your loop and close them at the end? You can do this by wrapping everything in a ResourceT and use allocate. withHdf5Path already us the MonadSafe from pipes, so the resources are opened only once during the process. (once per thread, because I process chunk of the data, one per thread). From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Thu May 21 07:15:08 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Thu, 21 May 2020 08:15:08 +0100 Subject: [Haskell-cafe] how to simplify ressources access and pipes steam In-Reply-To: References: Message-ID: <20200521071508.GG3598@cloudinit-builder> On Wed, May 20, 2020 at 06:23:31AM +0000, PICCA Frederic-Emmanuel wrote: > 1) I find the withUhvPathP sort of ugly, and I would like to know if > it could be written more elegantly, because I will need to write a > lot's of these function for different types. At first glance seems like you should be able to convert to ContT and use do notation. From K.Bleijenberg at lijbrandt.nl Fri May 22 11:29:06 2020 From: K.Bleijenberg at lijbrandt.nl (Kees Bleijenberg) Date: Fri, 22 May 2020 13:29:06 +0200 Subject: [Haskell-cafe] To much symbols in dll Message-ID: <000001d6302c$344a09d0$9cde1d70$@lijbrandt.nl> After a lot of trying I finally got my windows dll working (used by a Qt app). But after adding the package (aeson) I get: ld.exe: Error: export ordinal too large: 97839 There are a few messages about this problem. People talk about split-dll and gen-dll. But both seems more for building ghc itself. I tried gen-dll, but couldn't get it to work. I wonder if there is a solution for this problem? Kees -------------- next part -------------- An HTML attachment was scrubbed... URL: From leah at vuxu.org Fri May 22 20:40:13 2020 From: leah at vuxu.org (Leah Neukirchen) Date: Fri, 22 May 2020 22:40:13 +0200 Subject: [Haskell-cafe] Munich Virtual Haskell Meeting, 2020-05-25 @ 19:30 Message-ID: <87k113emaa.fsf@vuxu.org> Dear all, Next week, our monthly Munich Haskell Meeting will take place again on Monday, May 25 at 19:30. **Due to curfew in Bavaria, this meeting will take place online!** For details see here: http://muenchen.haskell.bayern/dates.html A Google Meet link to join the room will be provided on Monday. Everybody is welcome, especially the Haskellers from Bavaria that do not usually come to our Munich meetings due to travel distance! cu, -- Leah Neukirchen https://leahneukirchen.org/ From ivanperezdominguez at gmail.com Sat May 23 19:20:04 2020 From: ivanperezdominguez at gmail.com (Ivan Perez) Date: Sat, 23 May 2020 15:20:04 -0400 Subject: [Haskell-cafe] Reactive and Event-Based Languages and Systems (REBLS 2020) -- Call for Papers Message-ID: CALL FOR PAPERS 7th Workshop on Reactive and Event-based Languages and Systems (REBLS 2020) co-located with the SPLASH Conference Chicago, Illinois, USA Sun 15 - Fri 20 November 2020 Website: https://2020.splashcon.org/home/rebls-2020 IMPORTANT DATES Submission Deadline: 24 Jul 2020 Author Notification: 24 Aug 2020 Final Submission Deadline: 25 Sep 2020 INTRODUCTION Reactive programming and event-based programming are two closely related programming styles that are becoming more important with the ever increasing requirement for applications to run on the web or on mobile devices, and the advent of advanced High-Performance Computing (HPC) technology. A number of publications on middleware and language design -- so-called reactive and event-based languages and systems (REBLS) -- have already seen the light, but the field still raises several questions. For example, the interaction with mainstream language concepts is poorly understood, implementation technology is still lacking, and modularity mechanisms remain largely unexplored. Moreover, large applications are still to be developed, and, consequently, patterns and tools for developing large reactive applications are still in their infancy. This workshop will gather researchers in reactive and event-based languages and systems. The goal of the workshop is to exchange new technical research results and to better define the field by developing taxonomies and discussing overviews of the existing work. We welcome all submissions on reactive programming, functional reactive programming, and event- and aspect- oriented systems, including but not limited to: * Language design, implementation, runtime systems, program analysis, software metrics, patterns and benchmarks. * Formal models for reactive and event-based programming. * Study of the paradigm: interaction of reactive and event-based programming with existing language features such as object-oriented programming, pure functional programming, mutable state, concurrency. * Modularity and abstraction mechanisms in large systems. * Advanced event systems, event quantification, event composition, aspect-oriented programming for reactive applications. * Functional Reactive Programming (FRP), self-adjusting computation and incremental computing. * Synchronous languages, modeling real-time systems, safety-critical reactive and embedded systems. * Applications, case studies that show the efficacy of reactive programming. * Empirical studies that motivate further research in the field. * Patterns and best-practices. * Related fields, such as complex event processing, reactive data structures, view maintenance, constraint-based languages, and their integration with reactive programming. * Implementation technology, language runtimes, virtual machine support, compilers. * IDEs, Tools. The format of the workshop is that of a mini-conference. Participants can present their work in slots of 30 mins with Q&A included. Because of the declarative nature of reactive programs, it is often hard to understand their semantics just by looking at the code. We therefore also encourage authors to use their slots for presenting their work based on live demos. SUBMISSIONS REBLS encourages submissions of two types of papers: * Full papers: papers that describe complete research results. These papers will be published in the ACM digital library. * In-progress papers: papers that have the potential of triggering an interesting discussion at the workshop or present new ideas that require further systematic investigation. These papers will not be published in the ACM digital library. Format: * Submissions should use the ACM SIGPLAN Conference acmart Format with the two-column, sigplan Subformat, 10 point font, using Biolinum as sans-serif font and Libertine as serif font. All submissions should be in PDF format. If you use LaTeX or Word, please use the ACM SIGPLAN acmart Templates. The page http://www.sigplan.org/Resources/Author/#acmart-format contains instructions for authors, and a package that includes an example file acmart-sigplan.tex. * Authors are required to explicitly specify the type of paper in the submission (i.e., full paper, in-progress paper). * Full papers can be *up to* 12 pages in length, excluding references. In-progress papers can be *up to* 6 pages, excluding references. Papers do not need to make use of all pages, but they will be summarily rejected if they exceed the page limits. Instructions for the Authors: * Papers should be submitted through: https://rebls20.hotcrp.com/ * For fairness reasons, all submitted papers should conform to the formatting instructions. Submissions that violate these instructions will be summarily rejected. * Program Committee members are allowed to submit papers, but their papers will be held to a higher standard. * Papers must describe unpublished work that is not currently submitted for publication elsewhere as described by SIGPLAN’s Republication Policy (http://www.sigplan.org/Resources/Policies/Republication). Submitters should also be aware of ACM’s Policy and Procedures on Plagiarism. * All submissions are expected to comply with the ACM Policies for Authorship detailed at https://www.acm.org/publications/authors/information-for-authors. PROGRAM COMMITTEE Ivan Perez (PC Chair; NIA) Alan Jeffrey, Mozilla Research. Christiaan Baaij, QBayLogic. César Sánchez, IMDEA Software. Daniel Winograd-Cort, Target Corp. Edward Amsden, Black River Software, LLC. Guerric Chupin, University of Nottingham. Heinrich Apfelmus. Jonathan Thaler, University of Applied Sciences Vorarlberg. Louis Mandel, IBM Research. Manuel Bärenz, sonnen eServices GmbH. Marc Pouzet, Université Pierre et Marie Curie. Mark Santolucito, University of Yale. Neil Sculthorpe, University of Nottingham Trent. Noemi Rodrigues, Pontifícia Universidade Católica do Rio de Janeiro Oleksandra Bulgakova, Sukhomlynsky Mykolaiv National University Patrick Bahr, University of Copenhagen Takuo Watanabe, Tokyo Institute of Technology Tetsuo Kamina, Oita University Tom Van Cutsem, Nokia Bell Labs Yoshiki Ohshima, HARC / Y Combinator Research ORGANIZING COMMITTEE Guido Salvaneschi, TU Darmstadt, Germany Wolfgang De Meuter, Vrije Universiteit Brussel, Belgium Patrick Eugster, Universita della Svizzera Italiana, Switzerland Francisco Sant'Anna, Rio de Janeiro State University, Brazil Lukasz Ziarek, SUNY Buffalo, United States For any questions, please use the form on the website or contact the Chair at ivan.perezdominguez at nasa.gov. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dominikbollmann at gmail.com Sat May 23 20:40:42 2020 From: dominikbollmann at gmail.com (Dominik Bollmann) Date: Sat, 23 May 2020 22:40:42 +0200 Subject: [Haskell-cafe] [Open Kattis Problem] How can I speed up my A* algorithm and/or binomial heaps? Message-ID: <87367q1j1x.fsf@t450s> Hi Haskell-Cafe, I've been trying to solve the Problem "10 Kinds Of People" at https://open.kattis.com/problems/10kindsofpeople. My idea was to use the A* algorithm to check whether the destination can be reached from the source. To model the A* algorithm's priority queue, I also wrote a naive implementation of a binomial heap. I've attached the code snippet below. Unfortunately, my solution doesn't pass all of Open Kattis' test cases. In particular, it times out on the 22nd test case. Therefore I'm wondering how to speed up my solution. Did I make any obvious, silly mistakes? According to my time-profiling it seems that most of the time is spent in the binomial heap's deleteMin function. Maybe I should therefore not model the Heap as a list of trees, but rather as a vector of trees? Any hints on how to make the below snippet run faster is highly appreciated! :-) Thanks! Dominik ============================================= import Control.Monad import Data.Function import Data.Foldable (foldl') import Data.List (minimumBy, delete) import Data.Maybe import qualified Data.Set as S import qualified Data.Vector as V data Tree a = Node Int a [Tree a] deriving (Eq, Show) type Heap a = [Tree a] rank :: Tree a -> Int rank (Node k _ _) = k root :: Tree a -> a root (Node _ x _) = x children :: Tree a -> [Tree a] children (Node _ _ cs) = cs findMin :: Ord a => Heap a -> Maybe a findMin [] = Nothing findMin (t:ts) = Just . root $ foldl' selectMin t ts where selectMin e a | root e <= root a = e | otherwise = a empty :: Heap a empty = [] singleton :: Ord a => a -> Heap a singleton x = insert x empty insert :: Ord a => a -> Heap a -> Heap a insert x ts = foldr increment singleton ts where singleton = [Node 0 x []] increment t (h:hs) | rank t > rank h = t:h:hs | rank t == rank h = linkTrees t h : hs | rank t < rank h = error "insert: invalid case!" linkTrees :: Ord a => Tree a -> Tree a -> Tree a linkTrees t1 t2@(Node r x ts) | root t1 < root t2 = linkTrees t2 t1 | otherwise = Node (r+1) x (t1:ts) fromList :: Ord a => [a] -> Heap a fromList = foldr insert empty union :: Ord a => Heap a -> Heap a -> Heap a union h1 h2 = reverse $ reverse h1 `add` reverse h2 where add (t1:t2:t1s) t2s -- take care of the carry bit | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s add [] t2s = t2s add t1s [] = t1s add (t1:t1s) (t2:t2s) | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s | rank t1 < rank t2 = t1 : add t1s (t2:t2s) | rank t1 > rank t2 = t2 : add (t1:t1s) t2s deleteMin :: Ord a => Heap a -> Heap a deleteMin h = delete minTree h `union` children minTree where minTree = minimumBy (compare `on` root) h uncons :: Ord a => Heap a -> Maybe (a, Heap a) uncons h = do min <- findMin h pure (min, deleteMin h) data Entry p a = Entry { priority :: p, payload :: a } deriving Show instance Eq p => Eq (Entry p a) where (Entry p1 _) == (Entry p2 _) = p1 == p2 instance Ord p => Ord (Entry p a) where (Entry p1 _) <= (Entry p2 _) = p1 <= p2 data Point = Point { y :: !Int, x :: !Int } deriving (Eq, Ord, Show) data PeopleKind = Binary | Decimal deriving Eq newtype Map = Map { getMap :: (V.Vector (V.Vector PeopleKind)) } deriving Show instance Show PeopleKind where show Binary = "binary" show Decimal = "decimal" readMap :: Int -> Int -> IO Map readMap r c = do rows <- forM [1..r] $ \_ -> do row <- map readCell <$> getLine pure (V.fromListN c row) pure $ Map (V.fromList rows) where readCell :: Char -> PeopleKind readCell c = case c of '0' -> Binary '1' -> Decimal _ -> error "Map invalid!" readFromTo :: IO (Point, Point) readFromTo = do [fy, fx, ty, tx] <- map read . words <$> getLine pure (Point (fy-1) (fx-1), Point (ty-1) (tx-1)) reachable :: PeopleKind -> Map -> Point -> Point -> Bool reachable kind grid from to = go S.empty (singleton entry0) where entry0 = Entry (0 + estimate from to, 0) from go explored frontier = case uncons frontier of Nothing -> False Just (Entry (_, cost) point, frontier') | point == to -> True | point `S.member` explored -> go explored frontier' | otherwise -> let successors = map (mkEntry cost) $ neighbors kind grid point in go (S.insert point explored) (frontier' `union` fromList successors) mkEntry c s = Entry (c+1 + estimate s to, c+1) s estimate :: Point -> Point -> Double estimate (Point y1 x1) (Point y2 x2) = sqrt . fromIntegral $ (y2 - y1)^2 + (x2 - x1)^2 neighbors :: PeopleKind -> Map -> Point -> [Point] neighbors k (Map m) (Point y x) = catMaybes [left, right, top, bottom] where left = kindOk y (x-1) right = kindOk y (x+1) top = kindOk (y-1) x bottom = kindOk (y+1) x kindOk y x = do kind <- m V.!? y >>= (V.!? x) guard (kind == k) pure (Point y x) main :: IO () main = do [rows, cols] <- map read . words <$> getLine grid <- readMap rows cols queries <- read <$> getLine forM_ [1..queries] $ \_ -> do (from, to) <- readFromTo let kind = kindAt grid from if reachable kind grid from to then print kind else putStrLn "neither" where kindAt (Map m) (Point y x) = m V.! y V.! x From byorgey at gmail.com Sat May 23 21:02:39 2020 From: byorgey at gmail.com (Brent Yorgey) Date: Sat, 23 May 2020 16:02:39 -0500 Subject: [Haskell-cafe] [Open Kattis Problem] How can I speed up my A* algorithm and/or binomial heaps? In-Reply-To: <87367q1j1x.fsf@t450s> References: <87367q1j1x.fsf@t450s> Message-ID: Hi Dominik, Although optimizing your A* and binomial heap implementations is certainly a worthwhile challenge, I suspect it is not the real issue. The input can be a grid of size 1000 by 1000, and you have to answer up to 1000 queries. In the worst case, the path between the two query points could pass through about half the cells (imagine a path of 1's snaking back and forth). This suggests that even if your search algorithm took time linear in the number of cells it explored, it would still be too slow (a good rule of thumb is 10^8 operations per second, and we're looking at 10^3 * 10^3 * 10^3), and of course A* search is not even linear time. Hint: can you think of a way to preprocess the input so that queries can subsequently be answered very quickly, without doing any search? -Brent On Sat, May 23, 2020 at 3:42 PM Dominik Bollmann wrote: > > Hi Haskell-Cafe, > > I've been trying to solve the Problem "10 Kinds Of People" at > https://open.kattis.com/problems/10kindsofpeople. My idea was to use the > A* algorithm to check whether the destination can be reached from the > source. To model the A* algorithm's priority queue, I also wrote a naive > implementation of a binomial heap. I've attached the code snippet below. > > Unfortunately, my solution doesn't pass all of Open Kattis' test cases. > In particular, it times out on the 22nd test case. Therefore I'm > wondering how to speed up my solution. Did I make any obvious, silly > mistakes? > > According to my time-profiling it seems that most of the time is spent > in the binomial heap's deleteMin function. Maybe I should therefore not > model the Heap as a list of trees, but rather as a vector of trees? > > Any hints on how to make the below snippet run faster is highly > appreciated! :-) > > Thanks! > > Dominik > > ============================================= > > import Control.Monad > import Data.Function > import Data.Foldable (foldl') > import Data.List (minimumBy, delete) > import Data.Maybe > import qualified Data.Set as S > import qualified Data.Vector as V > > data Tree a = Node Int a [Tree a] deriving (Eq, Show) > type Heap a = [Tree a] > > rank :: Tree a -> Int > rank (Node k _ _) = k > > root :: Tree a -> a > root (Node _ x _) = x > > children :: Tree a -> [Tree a] > children (Node _ _ cs) = cs > > findMin :: Ord a => Heap a -> Maybe a > findMin [] = Nothing > findMin (t:ts) = Just . root $ foldl' selectMin t ts > where > selectMin e a > | root e <= root a = e > | otherwise = a > > empty :: Heap a > empty = [] > > singleton :: Ord a => a -> Heap a > singleton x = insert x empty > > insert :: Ord a => a -> Heap a -> Heap a > insert x ts = foldr increment singleton ts > where > singleton = [Node 0 x []] > increment t (h:hs) > | rank t > rank h = t:h:hs > | rank t == rank h = linkTrees t h : hs > | rank t < rank h = error "insert: invalid case!" > > linkTrees :: Ord a => Tree a -> Tree a -> Tree a > linkTrees t1 t2@(Node r x ts) > | root t1 < root t2 = linkTrees t2 t1 > | otherwise = Node (r+1) x (t1:ts) > > fromList :: Ord a => [a] -> Heap a > fromList = foldr insert empty > > union :: Ord a => Heap a -> Heap a -> Heap a > union h1 h2 = reverse $ reverse h1 `add` reverse h2 > where > add (t1:t2:t1s) t2s -- take care of the carry bit > | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s > add [] t2s = t2s > add t1s [] = t1s > add (t1:t1s) (t2:t2s) > | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s > | rank t1 < rank t2 = t1 : add t1s (t2:t2s) > | rank t1 > rank t2 = t2 : add (t1:t1s) t2s > > deleteMin :: Ord a => Heap a -> Heap a > deleteMin h = delete minTree h `union` children minTree > where minTree = minimumBy (compare `on` root) h > > uncons :: Ord a => Heap a -> Maybe (a, Heap a) > uncons h = do > min <- findMin h > pure (min, deleteMin h) > > data Entry p a = Entry { priority :: p, payload :: a } deriving Show > > instance Eq p => Eq (Entry p a) where > (Entry p1 _) == (Entry p2 _) = p1 == p2 > instance Ord p => Ord (Entry p a) where > (Entry p1 _) <= (Entry p2 _) = p1 <= p2 > > data Point = Point { y :: !Int, x :: !Int } deriving (Eq, Ord, Show) > data PeopleKind = Binary | Decimal deriving Eq > newtype Map = Map { getMap :: (V.Vector (V.Vector PeopleKind)) } deriving > Show > > instance Show PeopleKind where > show Binary = "binary" > show Decimal = "decimal" > > readMap :: Int -> Int -> IO Map > readMap r c = do > rows <- forM [1..r] $ \_ -> do > row <- map readCell <$> getLine > pure (V.fromListN c row) > pure $ Map (V.fromList rows) > where > readCell :: Char -> PeopleKind > readCell c = case c of > '0' -> Binary > '1' -> Decimal > _ -> error "Map invalid!" > > readFromTo :: IO (Point, Point) > readFromTo = do > [fy, fx, ty, tx] <- map read . words <$> getLine > pure (Point (fy-1) (fx-1), Point (ty-1) (tx-1)) > > reachable :: PeopleKind -> Map -> Point -> Point -> Bool > reachable kind grid from to = go S.empty (singleton entry0) > where > entry0 = Entry (0 + estimate from to, 0) from > go explored frontier = case uncons frontier of > Nothing -> False > Just (Entry (_, cost) point, frontier') > | point == to -> True > | point `S.member` explored -> go explored frontier' > | otherwise -> > let successors = map (mkEntry cost) $ neighbors kind grid point > in go (S.insert point explored) (frontier' `union` fromList > successors) > mkEntry c s = Entry (c+1 + estimate s to, c+1) s > > estimate :: Point -> Point -> Double > estimate (Point y1 x1) (Point y2 x2) = > sqrt . fromIntegral $ (y2 - y1)^2 + (x2 - x1)^2 > > neighbors :: PeopleKind -> Map -> Point -> [Point] > neighbors k (Map m) (Point y x) = > catMaybes [left, right, top, bottom] > where > left = kindOk y (x-1) > right = kindOk y (x+1) > top = kindOk (y-1) x > bottom = kindOk (y+1) x > kindOk y x = do > kind <- m V.!? y >>= (V.!? x) > guard (kind == k) > pure (Point y x) > > main :: IO () > main = do > [rows, cols] <- map read . words <$> getLine > grid <- readMap rows cols > queries <- read <$> getLine > forM_ [1..queries] $ \_ -> do > (from, to) <- readFromTo > let kind = kindAt grid from > if reachable kind grid from to > then print kind > else putStrLn "neither" > where > kindAt (Map m) (Point y x) = m V.! y V.! x > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dominikbollmann at gmail.com Sun May 24 19:07:24 2020 From: dominikbollmann at gmail.com (Dominik Bollmann) Date: Sun, 24 May 2020 21:07:24 +0200 Subject: [Haskell-cafe] [Open Kattis Problem] How can I speed up my A* algorithm and/or binomial heaps? In-Reply-To: References: <87367q1j1x.fsf@t450s> Message-ID: <87o8qdm9sj.fsf@t450s> Hi Brent, Thanks for your answer and hint! You gave me the clue how to approach the problem from a different angle, thereby not needing search nor a binomial heap anymore. I hope to implement it soon. :-) Cheers, Dominik. Brent Yorgey writes: > Hi Dominik, > > Although optimizing your A* and binomial heap implementations is certainly > a worthwhile challenge, I suspect it is not the real issue. The input can > be a grid of size 1000 by 1000, and you have to answer up to 1000 queries. > In the worst case, the path between the two query points could pass through > about half the cells (imagine a path of 1's snaking back and forth). This > suggests that even if your search algorithm took time linear in the number > of cells it explored, it would still be too slow (a good rule of thumb is > 10^8 operations per second, and we're looking at 10^3 * 10^3 * 10^3), and > of course A* search is not even linear time. > > Hint: can you think of a way to preprocess the input so that queries can > subsequently be answered very quickly, without doing any search? > > -Brent > > On Sat, May 23, 2020 at 3:42 PM Dominik Bollmann > wrote: > >> >> Hi Haskell-Cafe, >> >> I've been trying to solve the Problem "10 Kinds Of People" at >> https://open.kattis.com/problems/10kindsofpeople. My idea was to use the >> A* algorithm to check whether the destination can be reached from the >> source. To model the A* algorithm's priority queue, I also wrote a naive >> implementation of a binomial heap. I've attached the code snippet below. >> >> Unfortunately, my solution doesn't pass all of Open Kattis' test cases. >> In particular, it times out on the 22nd test case. Therefore I'm >> wondering how to speed up my solution. Did I make any obvious, silly >> mistakes? >> >> According to my time-profiling it seems that most of the time is spent >> in the binomial heap's deleteMin function. Maybe I should therefore not >> model the Heap as a list of trees, but rather as a vector of trees? >> >> Any hints on how to make the below snippet run faster is highly >> appreciated! :-) >> >> Thanks! >> >> Dominik >> >> ============================================= >> >> import Control.Monad >> import Data.Function >> import Data.Foldable (foldl') >> import Data.List (minimumBy, delete) >> import Data.Maybe >> import qualified Data.Set as S >> import qualified Data.Vector as V >> >> data Tree a = Node Int a [Tree a] deriving (Eq, Show) >> type Heap a = [Tree a] >> >> rank :: Tree a -> Int >> rank (Node k _ _) = k >> >> root :: Tree a -> a >> root (Node _ x _) = x >> >> children :: Tree a -> [Tree a] >> children (Node _ _ cs) = cs >> >> findMin :: Ord a => Heap a -> Maybe a >> findMin [] = Nothing >> findMin (t:ts) = Just . root $ foldl' selectMin t ts >> where >> selectMin e a >> | root e <= root a = e >> | otherwise = a >> >> empty :: Heap a >> empty = [] >> >> singleton :: Ord a => a -> Heap a >> singleton x = insert x empty >> >> insert :: Ord a => a -> Heap a -> Heap a >> insert x ts = foldr increment singleton ts >> where >> singleton = [Node 0 x []] >> increment t (h:hs) >> | rank t > rank h = t:h:hs >> | rank t == rank h = linkTrees t h : hs >> | rank t < rank h = error "insert: invalid case!" >> >> linkTrees :: Ord a => Tree a -> Tree a -> Tree a >> linkTrees t1 t2@(Node r x ts) >> | root t1 < root t2 = linkTrees t2 t1 >> | otherwise = Node (r+1) x (t1:ts) >> >> fromList :: Ord a => [a] -> Heap a >> fromList = foldr insert empty >> >> union :: Ord a => Heap a -> Heap a -> Heap a >> union h1 h2 = reverse $ reverse h1 `add` reverse h2 >> where >> add (t1:t2:t1s) t2s -- take care of the carry bit >> | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s >> add [] t2s = t2s >> add t1s [] = t1s >> add (t1:t1s) (t2:t2s) >> | rank t1 == rank t2 = add (linkTrees t1 t2 : t1s) t2s >> | rank t1 < rank t2 = t1 : add t1s (t2:t2s) >> | rank t1 > rank t2 = t2 : add (t1:t1s) t2s >> >> deleteMin :: Ord a => Heap a -> Heap a >> deleteMin h = delete minTree h `union` children minTree >> where minTree = minimumBy (compare `on` root) h >> >> uncons :: Ord a => Heap a -> Maybe (a, Heap a) >> uncons h = do >> min <- findMin h >> pure (min, deleteMin h) >> >> data Entry p a = Entry { priority :: p, payload :: a } deriving Show >> >> instance Eq p => Eq (Entry p a) where >> (Entry p1 _) == (Entry p2 _) = p1 == p2 >> instance Ord p => Ord (Entry p a) where >> (Entry p1 _) <= (Entry p2 _) = p1 <= p2 >> >> data Point = Point { y :: !Int, x :: !Int } deriving (Eq, Ord, Show) >> data PeopleKind = Binary | Decimal deriving Eq >> newtype Map = Map { getMap :: (V.Vector (V.Vector PeopleKind)) } deriving >> Show >> >> instance Show PeopleKind where >> show Binary = "binary" >> show Decimal = "decimal" >> >> readMap :: Int -> Int -> IO Map >> readMap r c = do >> rows <- forM [1..r] $ \_ -> do >> row <- map readCell <$> getLine >> pure (V.fromListN c row) >> pure $ Map (V.fromList rows) >> where >> readCell :: Char -> PeopleKind >> readCell c = case c of >> '0' -> Binary >> '1' -> Decimal >> _ -> error "Map invalid!" >> >> readFromTo :: IO (Point, Point) >> readFromTo = do >> [fy, fx, ty, tx] <- map read . words <$> getLine >> pure (Point (fy-1) (fx-1), Point (ty-1) (tx-1)) >> >> reachable :: PeopleKind -> Map -> Point -> Point -> Bool >> reachable kind grid from to = go S.empty (singleton entry0) >> where >> entry0 = Entry (0 + estimate from to, 0) from >> go explored frontier = case uncons frontier of >> Nothing -> False >> Just (Entry (_, cost) point, frontier') >> | point == to -> True >> | point `S.member` explored -> go explored frontier' >> | otherwise -> >> let successors = map (mkEntry cost) $ neighbors kind grid point >> in go (S.insert point explored) (frontier' `union` fromList >> successors) >> mkEntry c s = Entry (c+1 + estimate s to, c+1) s >> >> estimate :: Point -> Point -> Double >> estimate (Point y1 x1) (Point y2 x2) = >> sqrt . fromIntegral $ (y2 - y1)^2 + (x2 - x1)^2 >> >> neighbors :: PeopleKind -> Map -> Point -> [Point] >> neighbors k (Map m) (Point y x) = >> catMaybes [left, right, top, bottom] >> where >> left = kindOk y (x-1) >> right = kindOk y (x+1) >> top = kindOk (y-1) x >> bottom = kindOk (y+1) x >> kindOk y x = do >> kind <- m V.!? y >>= (V.!? x) >> guard (kind == k) >> pure (Point y x) >> >> main :: IO () >> main = do >> [rows, cols] <- map read . words <$> getLine >> grid <- readMap rows cols >> queries <- read <$> getLine >> forM_ [1..queries] $ \_ -> do >> (from, to) <- readFromTo >> let kind = kindAt grid from >> if reachable kind grid from to >> then print kind >> else putStrLn "neither" >> where >> kindAt (Map m) (Point y x) = m V.! y V.! x >> _______________________________________________ >> Haskell-Cafe mailing list >> To (un)subscribe, modify options or view archives go to: >> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >> Only members subscribed via the mailman list are allowed to post. From w-m at wmcode.nl Fri May 29 10:24:40 2020 From: w-m at wmcode.nl (Wiebe-Marten Wijnja) Date: Fri, 29 May 2020 12:24:40 +0200 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? Message-ID: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Greetings, everyone! Recently I was involved in a discussion on the new ML-style language 'gleam'. Gleam has for quite a while now only had an `Either a b` type, with all functions that in Haskell one would use a `Maybe a` for, working on an `Either a ()` instead. In the discussion(https://github.com/gleam-lang/gleam/issues/591), the language designers were asking the community whether it would make sense to add `Maybe` to the language as well, or keep using only `Either a ()`. My question: Is the difference between `Maybe a` and `Either a ()` only semantic and are they functionally equivalent, or are there differences in functionality as well? Have a nice day, ~Marten / Qqwy -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From leesteken at pm.me Fri May 29 10:32:35 2020 From: leesteken at pm.me (leesteken at pm.me) Date: Fri, 29 May 2020 10:32:35 +0000 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: On Friday, May 29, 2020 12:24 PM, Wiebe-Marten Wijnja wrote: > Greetings, everyone! > > Recently I was involved in a discussion on the new ML-style language > 'gleam'. > > Gleam has for quite a while now only had an `Either a b` type, > with all functions that in Haskell one would use a `Maybe a` for, > working on an `Either a ()` instead. > > In the discussion(https://github.com/gleam-lang/gleam/issues/591), the > language designers were asking the community whether it would make sense > to add `Maybe` to the language as well, > or keep using only `Either a ()`. > > My question: Is the difference between `Maybe a` and `Either a ()` only > semantic and are they functionally equivalent, > or are there differences in functionality as well? One can define instance Functor Maybe, and instance Functor (Either ()), but not something like instance Functor (\a -> Either a ()). Therefore, Either () a would be more like Maybe a than Either a (), in Haskell/GHC. kind regards, Arjen From jaro.reinders at gmail.com Fri May 29 10:36:27 2020 From: jaro.reinders at gmail.com (Jaro Reinders) Date: Fri, 29 May 2020 12:36:27 +0200 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: <428b5cf1-cf5b-b8cc-4319-2d7eb138b840@gmail.com> One difference between Maybe a and Either a () in Haskell is also that `Nothing < Just a` for any a. But `Right () > Left a` for any a. On 5/29/20 12:24 PM, Wiebe-Marten Wijnja wrote: > Greetings, everyone! > > Recently I was involved in a discussion on the new ML-style language > 'gleam'. > > Gleam has for quite a while now only had an `Either a b` type, > with all functions that in Haskell one would use a `Maybe a` for, > working on an `Either a ()` instead. > > In the discussion(https://github.com/gleam-lang/gleam/issues/591), the > language designers were asking the community whether it would make sense > to add `Maybe` to the language as well, > or keep using only `Either a ()`. > > > My question: Is the difference between `Maybe a` and `Either a ()` only > semantic and are they functionally equivalent, > or are there differences in functionality as well? > > > Have a nice day, > > ~Marten / Qqwy > > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. > From lemming at henning-thielemann.de Fri May 29 10:38:49 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Fri, 29 May 2020 12:38:49 +0200 (CEST) Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: On Fri, 29 May 2020, Wiebe-Marten Wijnja wrote: > Greetings, everyone! > > Recently I was involved in a discussion on the new ML-style language > 'gleam'. > > Gleam has for quite a while now only had an `Either a b` type, > with all functions that in Haskell one would use a `Maybe a` for, > working on an `Either a ()` instead. In Haskell `Maybe a` is more similar to `Either () a` than `Either a ()`. Either has one more redirection on the Left case. You can have both `Left undefined` and `Left ()` whereas Maybe can only have `Nothing`. I hardly think that people actually make use of this difference, though. Btw. from a software engineering point I'd prefer not to use Either for both exception handling with an according Monad and for cases where you just want to handle values of two possible types. I'd define an Except type for the exception usage. Could we remove Maybe in favor of Either? It would make some instances non-Haskell-98. E.g. instance C Maybe where is Haskell 98, but instance C (Either ()) where needs FlexibleInstances and instance (a ~ ()) => C (Either a) where needs TypeFamilies. Unless you find out that you can define a more general instance like instance (Super a) => C (Either a) where . From simon.jakobi at googlemail.com Fri May 29 12:20:09 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Fri, 29 May 2020 14:20:09 +0200 Subject: [Haskell-cafe] ANN: Data.Monoid.First and Data.Monoid.Last are here to stay Message-ID: Hi! I'm happy to report that the planned deprecation of Data.Monoid.{First,Last} [0] has finally been scrapped [1]. The original motivation for removing these newtypes of Maybe was to resolve the name conflict with Data.Semigroup.{First,Last} [2]. Unfortunately, while implementing the deprecation, I ended up discovering a whole host of problems with the suggested migration to (Maybe Data.Semigroup.First) and (Maybe Data.Semigroup.Last), which I have attempted to summarize in my email to the libraries mailing list [3]. I would like to thank everyone who contributed to the discussion of the matter, the CLC, and also everyone who pushed me to finally get the matter resolved. :) Cheers! Simon [0] http://hackage.haskell.org/package/base-4.14.0.0/docs/Data-Monoid.html#t:First [1] https://gitlab.haskell.org/ghc/ghc/-/commit/f44d7ae08442ae6227db37cacc97fe0def8017c5 [2] https://mail.haskell.org/pipermail/libraries/2018-April/028712.html [3] https://mail.haskell.org/pipermail/libraries/2020-April/030357.html From zemyla at gmail.com Fri May 29 14:48:39 2020 From: zemyla at gmail.com (Zemyla) Date: Fri, 29 May 2020 09:48:39 -0500 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: "Nothing" uses the same memory slot no matter how many times it's used, but "Left ()" will more than likely create a new object every time, or at the very least one for each module where it's used. Eq and Ord instances get slightly slower because they have to compare () with () every time they receive a pair of Lefts. Where you would pass "x" into the "maybe" deconstructor function, now you would have to pass "const x" to "either", which again uses more memory and (more importantly) more cognitive space. We have the problem other people have mentioned where FlexibleInstances or TypeFamilies/GADTs have to be used to define instances for Either (). However, the biggest problem is that Maybe is not actually isomorphic to Either () in a lazy language like Haskell. Maybe has * Nothing * Just x However, Either () has * Left () * Right x * Left undefined And that final value causes infinite problems, particularly when you pass it to other functions which handle strictness on the Left argument differently. Is the Eq () instance strict or lazy in its arguments? I honestly would not be able to tell you without firing up an instance of GHCi. I've seen different libraries which define singleton objects define it in different ways. On Fri, May 29, 2020, 05:40 Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Fri, 29 May 2020, Wiebe-Marten Wijnja wrote: > > > Greetings, everyone! > > > > Recently I was involved in a discussion on the new ML-style language > > 'gleam'. > > > > Gleam has for quite a while now only had an `Either a b` type, > > with all functions that in Haskell one would use a `Maybe a` for, > > working on an `Either a ()` instead. > > In Haskell `Maybe a` is more similar to `Either () a` than `Either a ()`. > > Either has one more redirection on the Left case. You can have both `Left > undefined` and `Left ()` whereas Maybe can only have `Nothing`. I hardly > think that people actually make use of this difference, though. > > Btw. from a software engineering point I'd prefer not to use Either for > both exception handling with an according Monad and for cases where you > just want to handle values of two possible types. I'd define an Except > type for the exception usage. > > Could we remove Maybe in favor of Either? It would make some instances > non-Haskell-98. E.g. > > instance C Maybe where > > is Haskell 98, but > > instance C (Either ()) where > > needs FlexibleInstances and > > instance (a ~ ()) => C (Either a) where > > needs TypeFamilies. > > Unless you find out that you can define a more general instance like > > instance (Super a) => C (Either a) where > > . > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: From albert+haskell at zeitkraut.de Fri May 29 14:49:39 2020 From: albert+haskell at zeitkraut.de (Albert Krewinkel) Date: Fri, 29 May 2020 16:49:39 +0200 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: <87h7vyaj98.fsf@zeitkraut.de> Wiebe-Marten Wijnja writes: > My question: Is the difference between `Maybe a` and `Either a ()` only > semantic and are they functionally equivalent, > or are there differences in functionality as well? One difference that comes to mind is that there is only one way to write the failing case for `Maybe a` (namely `Nothing`), but two ways for `Either a ()`: `Right ()` and `Right ⊥`. -- Albert Krewinkel GPG: 8eed e3e2 e8c5 6f18 81fe e836 388d c0b2 1f63 1124 From ben.franksen at online.de Fri May 29 19:51:40 2020 From: ben.franksen at online.de (Ben Franksen) Date: Fri, 29 May 2020 21:51:40 +0200 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: Am 29.05.20 um 12:24 schrieb Wiebe-Marten Wijnja: > Recently I was involved in a discussion on the new ML-style language > 'gleam'. > > Gleam has for quite a while now only had an `Either a b` type, > with all functions that in Haskell one would use a `Maybe a` for, > working on an `Either a ()` instead. > > In the discussion(https://github.com/gleam-lang/gleam/issues/591), the > language designers were asking the community whether it would make sense > to add `Maybe` to the language as well, > or keep using only `Either a ()`. A separate data type makes the intention clearer and (as others have stated) is a bit more memory efficient (in Haskell, but I think in an ML-like language, too). The disadvantage is that you cannot easily re-use existing functionality. So there is a danger that implementations of functions on Maybe deviate from those for Either () for no good reason. > My question: Is the difference between `Maybe a` and `Either a ()` only > semantic and are they functionally equivalent, I'd say any semantic difference (apart from laziness) between (Maybe a) and (Either () a) is more accidental than expressly desired. > or are there differences in functionality as well? There seem to be some, as was previously observed (e.g. the Ord instance). Whether this was intended is questionable. The mentioned differences regarding () vs. bottom are, I think, not of particular interest to you: if gleam is ML-style then it probably is a strict language, and thus Maybe and Either () would be fully equivalent as data types. Cheers Ben From raoknz at gmail.com Sat May 30 02:21:28 2020 From: raoknz at gmail.com (Richard O'Keefe) Date: Sat, 30 May 2020 14:21:28 +1200 Subject: [Haskell-cafe] Why does Haskell have both `Maybe a` and `Either a ()`? In-Reply-To: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> References: <556a9c53-eb40-07d8-0a76-b84d0ee8d1bb@wmcode.nl> Message-ID: There is a subtle difference between Haskell Either and Gleam Result. Haskell: data Either a b = Left a | Right b ... Gleam: pub type Result(a, e) { Ok(a) Error(e) } The computer doesn't care, but it's important for human thinking: ** Nothing is *not* an Error. Suppose for example I have a function next_smaller_prime :: Int -> Maybe Int where next_smaller_prime 10 -> Just 7 and next_smaller_prime 2 -> Nothing The second case is not an error. You get the answer Nothing because the function *worked*, not because it didn't. To return Error Nil is to commit the YouTube (social) offence: "You are an evil-doer who has done something wrong. I refuse to tell you WHAT you did wrong, so you can't fix it, you wrong-thinking PEASANT." Seriously, if you have decided to return Error(x), x had BETTER be a 'reason' (as Erlang calls it) for WHY it is an error. The pattern in Erlang is, after all, {ok,Result} | {error,Reason}. sans_reason (Left _) = Nothing sans_reason (Right x) = Just x with_reason (Nothing) s = Left s with_reason (Just x) _ = Right x are trivial conversion functions. As I said, the computer does not care. There are (at least) three different situations we can consider. (1) Sometimes there is no answer. Typically a search. In this case, Maybe is appropriate. (2) Sometimes you asked a question which fails to have an answer for a reason. In this case, Either is appropriate. (3) Sometimes you asked a sensible question for which the system might have been expected to produce an answer, but something went wrong. Numeric overflow, database connection shut down unexpectedly, hard drive developed a bad block. In this case, an exception is appropriate. And of course there are other reasons to use Either. Think of divide-and-conquer: classify :: Problem -> Either SubProblems EasyProblem. Because Gleam's Result isn't Haskell's Either in terms of connotations for human beings, even if they are basically the same to a computer. On Fri, 29 May 2020 at 22:26, Wiebe-Marten Wijnja wrote: > Greetings, everyone! > > Recently I was involved in a discussion on the new ML-style language > 'gleam'. > > Gleam has for quite a while now only had an `Either a b` type, > with all functions that in Haskell one would use a `Maybe a` for, > working on an `Either a ()` instead. > > In the discussion(https://github.com/gleam-lang/gleam/issues/591), the > language designers were asking the community whether it would make sense > to add `Maybe` to the language as well, > or keep using only `Either a ()`. > > > My question: Is the difference between `Maybe a` and `Either a ()` only > semantic and are they functionally equivalent, > or are there differences in functionality as well? > > > Have a nice day, > > ~Marten / Qqwy > > > _______________________________________________ > Haskell-Cafe mailing list > To (un)subscribe, modify options or view archives go to: > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe > Only members subscribed via the mailman list are allowed to post. -------------- next part -------------- An HTML attachment was scrubbed... URL: