From clintonmead at gmail.com Sun Jan 2 08:29:32 2022 From: clintonmead at gmail.com (Clinton Mead) Date: Sun, 2 Jan 2022 19:29:32 +1100 Subject: [Haskell-cafe] Managing state between client/server (frontend/backend) Message-ID: A happy new year to all the Haskell community. My current role involves an app with a Scala backend and a React/Redux Javascript frontend. What should be quite simple tasks are made difficult/impossible, firstly by the fact if you even touch a Javascript codebase in any significant way you break the code in weird and wonderful ways, which may only be apparent as random runtime errors days, weeks or months in the future, but another issue is that tracking some bug back from the browser to the backend and the database is a nightmare because it's far from obvious what's going on across the language boundary between Scala and Javascript, particularly as everything is being flattened to JSON across that boundary. Anyway, I was thinking of a better way of doing this, and I thought it would be nice if much of the code was shared between the browser frontend and backend server though a common datatype, with the frontend just compiled with GHCJS. Some of the state to the client could be readonly, and some writable. The actual details of pushing the data back and forth would be abstracted away (as much as possible). When the client does writes, it wouldn't need to wait for the server to process these writes, it could just save these on the client side state, and send them off to the server to record, but otherwise continue on. There's quite a few nuances here I've started to think about (and there's likely more I haven't thought about) and given that I don't think this idea is particularly novel, are there any libraries out there that already do roughly what I'm talking about here? If someone has already thought this through I don't want to reinvent the wheel. -------------- next part -------------- An HTML attachment was scrubbed... URL: From alec.theriault at gmail.com Sun Jan 2 15:54:31 2022 From: alec.theriault at gmail.com (Alec Theriault) Date: Sun, 2 Jan 2022 10:54:31 -0500 Subject: [Haskell-cafe] Managing state between client/server (frontend/backend) In-Reply-To: References: Message-ID: Hi Clinton, At the risk of being a little bit off-topic, have you considered using Scala.js instead of GHCJS (especially since you say the backend is already Scala)? You get the same benefits as what you describe (datatypes shared across the client/server, fearless refactoring, etc.). We do this at work and use the following tech stack: - Core data types are defined in a project that is cross compiled for JVM and JS targets (using the sbt-crossproject plugin). We define the entire schema of our REST API in this project, using endpoints4s (more specifically, the algebra project). - The client is written in Scala.js using React. The Scala.js React bindings we use (basically the typed API on top of React) come from slinky although scalajs-react is another popular library for this. We derive a REST API client from the core project using the endpoints4s xhr-client interpreter, so each API call is just a function from the endpoint inputs to its outputs. We compile all of the Scala.js code into one minified bundle which we serve up as a resource from the backend using the SBT scalajs-bundler plugin. - The backend exposes an Akka HTTP server, where we provide implementations for all of the endpoints using the endpoints4s akka-http interpreter (if your backend already leverages a Scala HTTP server, there's a good chance there's an endpoints4s interpreter for it). The net effect is that all the project source is in Scala and the entire build process is unified in SBT. This simplifies development quite a bit since one SBT command will build everything and you get type errors if you change the API without changing both the client and the server. In any case, I'd be very interested in hearing about Haskell solutions to this though - especially how folks handle the build system integration of GHCJS and GHC. I believe that servant fills the niche of endpoint4s and miso gets used for building the actual client apps, although I've not used either. Happy new year, -Alec On Sun, Jan 2, 2022 at 3:30 AM Clinton Mead wrote: > A happy new year to all the Haskell community. > > My current role involves an app with a Scala backend and a React/Redux > Javascript frontend. What should be quite simple tasks are made > difficult/impossible, firstly by the fact if you even touch a Javascript > codebase in any significant way you break the code in weird and wonderful > ways, which may only be apparent as random runtime errors days, weeks or > months in the future, but another issue is that tracking some bug back from > the browser to the backend and the database is a nightmare because it's far > from obvious what's going on across the language boundary between Scala and > Javascript, particularly as everything is being flattened to JSON across > that boundary. > > Anyway, I was thinking of a better way of doing this, and I thought it > would be nice if much of the code was shared between the browser frontend > and backend server though a common datatype, with the frontend just > compiled with GHCJS. > > Some of the state to the client could be readonly, and some writable. The > actual details of pushing the data back and forth would be abstracted away > (as much as possible). When the client does writes, it wouldn't need to > wait for the server to process these writes, it could just save these on > the client side state, and send them off to the server to record, but > otherwise continue on. > > There's quite a few nuances here I've started to think about (and there's > likely more I haven't thought about) and given that I don't think this idea > is particularly novel, are there any libraries out there that already do > roughly what I'm talking about here? If someone has already thought this > through I don't want to reinvent the wheel. > _______________________________________________ > 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 tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Jan 3 12:42:21 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 3 Jan 2022 12:42:21 +0000 Subject: [Haskell-cafe] Do something about Cabal? In-Reply-To: <20201211150938.GP4433@cloudinit-builder> References: <20201210131644.GC902@extensa> <7edeb28fe01dd8ab6589fbaaec043ce4@jackkelly.name> <887B1DEB-2611-4C3D-A0B1-AC93840B64DD@icloud.com> <20201211135457.GL4433@cloudinit-builder> <20201211150938.GP4433@cloudinit-builder> Message-ID: <20220103124221.GD15536@cloudinit-builder> On Fri, Dec 11, 2020 at 03:09:38PM +0000, Tom Ellis wrote: > On Fri, Dec 11, 2020 at 01:54:57PM +0000, Tom Ellis wrote: > > On Fri, Dec 11, 2020 at 10:31:23AM +0100, Immanuel Litzroth wrote: > > > I found the whole cabal experience confusing and not well documented. > > > I kept finding blogs online > > > that were not working anymore in my version of cabal > > > > If you find outdated Haskell-related documentation please report it at > > > > https://github.com/tomjaguarpaw/tilapia/issues/new > > And on that point, I am tracking your particular issue with > https://www.haskell.org/cabal/ as > > https://github.com/tomjaguarpaw/tilapia/issues/44 I have subsequently fixed most of the outdated Cabal documentation on http://www.haskell.org/cabal. For more details see * https://github.com/tomjaguarpaw/tilapia/issues/44 * https://github.com/tomjaguarpaw/tilapia/issues/47 Tom From lists at richarde.dev Mon Jan 3 14:26:41 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Mon, 3 Jan 2022 14:26:41 +0000 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> Message-ID: <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> > On Dec 31, 2021, at 8:33 AM, Dmitriy Matrosov wrote: > >> - GHC does not distinguish between types and kinds, since GHC 8.0. Much literature about Haskell continues to make this distinction, including GHC's own error messages (at some implementation challenge, even). This is because, most of the time, programs don't cross the line between types and kinds, and this distinction can be helpful. However, your code does shuttle ideas back and forth across the line, and so the distinction is harmful. Bottom line here: treat types and kinds as synonyms. The design of Haskell does, internally. > > So.. does this mean that there are only two "things" now: "something" > and "type of something". And this "something" may be either value or > type. And when "something" is type, it's type is what was previously > called kind? I would say Haskell has terms and types. It also has two relations: type-of-term and type-of-type. The type of a term (using the type-of-term relation) connects a term to a type. The type of a type (using the type-of-type relation) connects a type with another type. Some would say that the type-of-type relation connects a type with a kind, but "kind" is really just a synonym for "type". The design of Haskell has arranged that, for data constructors, the type-of-term relation and the type-of-type relation coincide. That is, the phrase `Just :: forall a. a -> Maybe a` is true both when `Just` is a term (and we're talking about the type-of-term relation) and when `Just` is a type (and we're talking about the type-of-type relation). > > And the exact same type variable may denote the type of both > "something"-s (values and types) at the same time (i.e. in the one > expression)? I think so -- I'm not sure I understand your phrasing fully. Because types and kinds are the same, one type variable may be used both in a type-of-a-term and in the type-of-a-type. > And does the error: > > coerce-existential-with-type-level-maybe.lhs:22:3: error: > • Type variable ‘t’ is mentioned in the RHS, > but not bound on the LHS of the family instance > • In the type instance declaration for ‘ToType’ > In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ > | > 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where > | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... > > when i try to apply 'Nothing to @Type instead of @t occurs, because > full form of associated type family is > > type ToType ('Nothing @Type) = t > > and variable 't' becomes unbound? I wouldn't quite say t is unbound there -- it refers to the t in the instance head. What's more troublesome is that, when GHC is trying to reduce `ToType (Nothing @Type)`, it has no way of knowing what `t` is. This is why GHC requires that all variables mentioned in the RHS of an associated type equation are also mentioned on the left. I hope this helps! Richard From simon.jakobi at googlemail.com Mon Jan 3 15:35:53 2022 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Mon, 3 Jan 2022 16:35:53 +0100 Subject: [Haskell-cafe] Do something about Cabal? In-Reply-To: <20220103124221.GD15536@cloudinit-builder> References: <20201210131644.GC902@extensa> <7edeb28fe01dd8ab6589fbaaec043ce4@jackkelly.name> <887B1DEB-2611-4C3D-A0B1-AC93840B64DD@icloud.com> <20201211135457.GL4433@cloudinit-builder> <20201211150938.GP4433@cloudinit-builder> <20220103124221.GD15536@cloudinit-builder> Message-ID: Wow, that's pretty nice! :) The main info that I think would be useful to add is how to contribute to this documentation, i.e. a link to the source repo. Am Mo., 3. Jan. 2022 um 13:43 Uhr schrieb Tom Ellis : > > On Fri, Dec 11, 2020 at 03:09:38PM +0000, Tom Ellis wrote: > > On Fri, Dec 11, 2020 at 01:54:57PM +0000, Tom Ellis wrote: > > > On Fri, Dec 11, 2020 at 10:31:23AM +0100, Immanuel Litzroth wrote: > > > > I found the whole cabal experience confusing and not well documented. > > > > I kept finding blogs online > > > > that were not working anymore in my version of cabal > > > > > > If you find outdated Haskell-related documentation please report it at > > > > > > https://github.com/tomjaguarpaw/tilapia/issues/new > > > > And on that point, I am tracking your particular issue with > > https://www.haskell.org/cabal/ as > > > > https://github.com/tomjaguarpaw/tilapia/issues/44 > > I have subsequently fixed most of the outdated Cabal documentation on > http://www.haskell.org/cabal. For more details see > > * https://github.com/tomjaguarpaw/tilapia/issues/44 > > * https://github.com/tomjaguarpaw/tilapia/issues/47 > > Tom > > _______________________________________________ > 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 tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Jan 3 17:06:42 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 3 Jan 2022 17:06:42 +0000 Subject: [Haskell-cafe] Do something about Cabal? In-Reply-To: References: <20201210131644.GC902@extensa> <7edeb28fe01dd8ab6589fbaaec043ce4@jackkelly.name> <887B1DEB-2611-4C3D-A0B1-AC93840B64DD@icloud.com> <20201211135457.GL4433@cloudinit-builder> <20201211150938.GP4433@cloudinit-builder> <20220103124221.GD15536@cloudinit-builder> Message-ID: <20220103170642.GB31258@cloudinit-builder> Thanks! The contribution process to haskell.org is explained on its repo README: https://github.com/haskell-infra/www.haskell.org#haskellorg-website There are some subsites of haskell.org that are not handled at the above repo. I have a PR[1] out to document them. In the meantime you can see them at: https://github.com/tomjaguarpaw/www.haskell.org/tree/subsites#subsites Tom [1]: https://github.com/haskell-infra/www.haskell.org/pull/103 On Mon, Jan 03, 2022 at 04:35:53PM +0100, Simon Jakobi via Haskell-Cafe wrote: > Wow, that's pretty nice! :) > > The main info that I think would be useful to add is how to contribute > to this documentation, i.e. a link to the source repo. > > Am Mo., 3. Jan. 2022 um 13:43 Uhr schrieb Tom Ellis > : > > > > On Fri, Dec 11, 2020 at 03:09:38PM +0000, Tom Ellis wrote: > > > On Fri, Dec 11, 2020 at 01:54:57PM +0000, Tom Ellis wrote: > > > > On Fri, Dec 11, 2020 at 10:31:23AM +0100, Immanuel Litzroth wrote: > > > > > I found the whole cabal experience confusing and not well documented. > > > > > I kept finding blogs online > > > > > that were not working anymore in my version of cabal > > > > > > > > If you find outdated Haskell-related documentation please report it at > > > > > > > > https://github.com/tomjaguarpaw/tilapia/issues/new > > > > > > And on that point, I am tracking your particular issue with > > > https://www.haskell.org/cabal/ as > > > > > > https://github.com/tomjaguarpaw/tilapia/issues/44 > > > > I have subsequently fixed most of the outdated Cabal documentation on > > http://www.haskell.org/cabal. For more details see > > > > * https://github.com/tomjaguarpaw/tilapia/issues/44 > > > > * https://github.com/tomjaguarpaw/tilapia/issues/47 From frederic-emmanuel.picca at synchrotron-soleil.fr Mon Jan 10 08:47:34 2022 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Mon, 10 Jan 2022 09:47:34 +0100 (CET) Subject: [Haskell-cafe] strange link error Message-ID: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> Hello, I try to build a project which use C libraries. during the developpement I want to link directly with the work in progress libraries. So I added this in cabal. executable binoculars-ng [...] if flag(useHklDev) pkgconfig-depends: gobject-2.0 ghc-options: -pgml ghc-options: gcc ghc-options: "-optl-Wl,--allow-multiple-definition" ghc-options: "-optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive" ghc-options: "-optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive" at the end I have a working executable. Building executable 'binoculars-ng' for hkl-0.1.0.0.. [1 of 1] Compiling Main ( app/Binoculars.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp/Main.o ) Linking /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng ... But now I would like to create an unit test so I added this in cabal test-suite hkl-test [...] if flag(useHklDev) pkgconfig-depends: gobject-2.0 ghc-options: -pgml ghc-options: gcc ghc-options: "-optl-Wl,--allow-multiple-definition" ghc-options: "-optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive" ghc-options: "-optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive" but this time during the compilation I end up with this error message [1 of 3] Compiling Paths_hkl ( /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/autogen/Paths_hkl.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/hkl-test-tmp/Paths_hkl.o ) [2 of 3] Compiling BinocularsSpec ( test/BinocularsSpec.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/hkl-test-tmp/BinocularsSpec.o ) : /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/build/libHShkl-0.1.0.0-inplace-ghc8.8.4.so: undefined symbol: hkl_binoculars_cube_free both the executable and the test use this hkl_binoculars_cube_free function. So are you aware of a difference between test suit and executable during the build. more precisely are both executables compiled differently ? thanks for you help Frederic From allbery.b at gmail.com Mon Jan 10 10:15:53 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 10 Jan 2022 05:15:53 -0500 Subject: [Haskell-cafe] strange link error In-Reply-To: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: That error message looks like it's coming from TH instead of final link, so you may need to do something else to make it available to TH during compile. On Mon, Jan 10, 2022 at 3:50 AM PICCA Frederic-Emmanuel wrote: > > Hello, I try to build a project which use C libraries. > > during the developpement I want to link directly with the work in progress libraries. > So I added this in cabal. > > executable binoculars-ng > [...] > > if flag(useHklDev) > pkgconfig-depends: gobject-2.0 > ghc-options: -pgml > ghc-options: gcc > ghc-options: "-optl-Wl,--allow-multiple-definition" > ghc-options: "-optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive" > ghc-options: "-optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive" > > at the end I have a working executable. > > Building executable 'binoculars-ng' for hkl-0.1.0.0.. > [1 of 1] Compiling Main ( app/Binoculars.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp/Main.o ) > Linking /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng ... > > > But now I would like to create an unit test so I added this in cabal > > test-suite hkl-test > [...] > if flag(useHklDev) > pkgconfig-depends: gobject-2.0 > ghc-options: -pgml > ghc-options: gcc > ghc-options: "-optl-Wl,--allow-multiple-definition" > ghc-options: "-optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive" > ghc-options: "-optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive" > > but this time during the compilation I end up with this error message > > [1 of 3] Compiling Paths_hkl ( /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/autogen/Paths_hkl.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/hkl-test-tmp/Paths_hkl.o ) > [2 of 3] Compiling BinocularsSpec ( test/BinocularsSpec.hs, /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/t/hkl-test/build/hkl-test/hkl-test-tmp/BinocularsSpec.o ) > : /home/experiences/instrumentation/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/build/libHShkl-0.1.0.0-inplace-ghc8.8.4.so: undefined symbol: hkl_binoculars_cube_free > > both the executable and the test use this hkl_binoculars_cube_free function. > > So are you aware of a difference between test suit and executable during the build. > > more precisely are both executables compiled differently ? > > thanks for you help > > 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. -- brandon s allbery kf8nh allbery.b at gmail.com From frederic-emmanuel.picca at synchrotron-soleil.fr Mon Jan 10 10:50:51 2022 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Mon, 10 Jan 2022 11:50:51 +0100 (CET) Subject: [Haskell-cafe] strange link error In-Reply-To: References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> ----- Brandon Allbery a écrit : > That error message looks like it's coming from TH instead of final > link, so you may need to do something else to make it available to TH > during compile. I used the -v option in order to have detailed error message executable --------------- creating /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp /usr/bin/ghc --make -no-link -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i. -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen/cabal_macros.h -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id containers-0.6.2.1 -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id exceptions-0.10.4-9CfD2hJyZLFIbks3iYGf0k -package-id filepath-1.4.2.1 -package-id hkl-0.1.0.0-inplace -package-id monad-logger-0.3.34-CJMMf2yR5GpALmIIglLyst -package-id monad-loops-0.4.3-9fN6QF5xEO8BUJUobxjHs -package-id optparse-applicative-0.15.1.0-GiY4uo4FBQRKuBqOktTXko -package-id pipes-4.3.14-KiHrcdQOQdo1w0hHviOVEE -package-id text-1.2.4.0 -package-id transformers-0.5.6.2 -package-id vector-0.12.1.2-C2W44iPdAFeHo4yLU081Gd -XHaskell2010 ./app/Binoculars.hs -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages test ----- /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp /usr/bin/ghc --make -no-link -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -itest -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen/cabal_macros.h -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id config-ini-0.2.4.0-D7dieWR57bgihPQO3mLYW -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id hkl-0.1.0.0-inplace -package-id hspec-2.7.1-5JvuKFX0Z3iFazfgnEEvF6 -package-id path-0.7.0-ItQkMO2BJUADmjR5L3rHpY -package-id text-1.2.4.0 -XHaskell2010 BinocularsSpec Paths_hkl test/Spec.hs -threaded '-rtsopts=all' '-with-rtsopts=-K1k' -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages [1 of 1] Compiling Main ( app/Binoculars.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp/Main.o ) [1 of 3] Compiling Paths_hkl ( /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen/Paths_hkl.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp/Paths_hkl.o ) [2 of 3] Compiling BinocularsSpec ( test/BinocularsSpec.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp/BinocularsSpec.o ) : /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/build/libHShkl-0.1.0.0-inplace-ghc8.8.4.so: undefined symbol: hkl_binoculars_cube_free Linking... /usr/bin/ghc --make -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i. -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen/cabal_macros.h -lgobject-2.0 -lglib-2.0 -L/home/picca/src/repo.or.cz/hkl/binoculars/ -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id containers-0.6.2.1 -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id exceptions-0.10.4-9CfD2hJyZLFIbks3iYGf0k -package-id filepath-1.4.2.1 -package-id hkl-0.1.0.0-inplace -package-id monad-logger-0.3.34-CJMMf2yR5GpALmIIglLyst -package-id monad-loops-0.4.3-9fN6QF5xEO8BUJUobxjHs -package-id optparse-applicative-0.15.1.0-GiY4uo4FBQRKuBqOktTXko -package-id pipes-4.3.14-KiHrcdQOQdo1w0hHviOVEE -package-id text-1.2.4.0 -package-id transformers-0.5.6.2 -package-id vector-0.12.1.2-C2W44iPdAFeHo4yLU081Gd -XHaskell2010 ./app/Binoculars.hs -o /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages Linking /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng ... CallStack (from HasCallStack): die', called at ./Distribution/Client/ProjectOrchestration.hs:1035:55 in main:Distribution.Client.ProjectOrchestration cabal: Failed to build hkl-0.1.0.0-inplace-hkl-test. the difference is that there is no link phase for the executable binary (it has only one file). I see no reference to TH during the compilation of this part of the code. (It is true thaht I use TH in the librarie). Cheers Fred From allbery.b at gmail.com Mon Jan 10 10:54:58 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 10 Jan 2022 05:54:58 -0500 Subject: [Haskell-cafe] strange link error In-Reply-To: <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: In that case you were missing part of the error message, since it came up at 2 out of 3 compiled and referenced "command line" instead of an object file, and comes before the "Linking" message. Given the forced link stuff I wonder if you need -Wl,-u -Wl,hkl_binoculars_cube_free (or some variant thereof). On Mon, Jan 10, 2022 at 5:51 AM PICCA Frederic-Emmanuel wrote: > > > ----- Brandon Allbery a écrit : > > That error message looks like it's coming from TH instead of final > > link, so you may need to do something else to make it available to TH > > during compile. > > I used the -v option in order to have detailed error message > > executable > --------------- > > creating > /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp > /usr/bin/ghc --make -no-link -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i. -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen/cabal_macros.h -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id containers-0.6.2.1 -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id exceptions-0.10.4-9CfD2hJyZLFIbks3iYGf0k -package-id filepath-1.4.2.1 -package-id hkl-0.1.0.0-inplace -package-id monad-logger-0.3.34-CJMMf2yR5GpALmIIglLyst -package-id monad-loops-0.4.3-9fN6QF5xEO8BUJUobxjHs -package-id optparse-applicative-0.15.1.0-GiY4uo4FBQRKuBqOktTXko -package-id pipes-4.3.14-KiHrcdQOQdo1w0hHviOVEE -package-id text-1.2.4.0 -package-id transformers-0.5.6.2 -package-id vector-0.12.1.2-C2W44iPdAFeHo4yLU081Gd -XHaskell2010 ./app/Binoculars.hs -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages > > test > ----- > /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp > /usr/bin/ghc --make -no-link -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -itest -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen/cabal_macros.h -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id config-ini-0.2.4.0-D7dieWR57bgihPQO3mLYW -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id hkl-0.1.0.0-inplace -package-id hspec-2.7.1-5JvuKFX0Z3iFazfgnEEvF6 -package-id path-0.7.0-ItQkMO2BJUADmjR5L3rHpY -package-id text-1.2.4.0 -XHaskell2010 BinocularsSpec Paths_hkl test/Spec.hs -threaded '-rtsopts=all' '-with-rtsopts=-K1k' -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages > [1 of 1] Compiling Main ( app/Binoculars.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp/Main.o ) > [1 of 3] Compiling Paths_hkl ( /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/autogen/Paths_hkl.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp/Paths_hkl.o ) > [2 of 3] Compiling BinocularsSpec ( test/BinocularsSpec.hs, /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/hkl-test/build/hkl-test/hkl-test-tmp/BinocularsSpec.o ) > : /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/build/libHShkl-0.1.0.0-inplace-ghc8.8.4.so: undefined symbol: hkl_binoculars_cube_free > Linking... > /usr/bin/ghc --make -fbuilding-cabal-package -O -static -outputdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -odir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -hidir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -stubdir /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -i. -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -i/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/global-autogen -I/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng-tmp -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -optP-include -optP/home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/autogen/cabal_macros.h -lgobject-2.0 -lglib-2.0 -L/home/picca/src/repo.or.cz/hkl/binoculars/ -hide-all-packages -Wmissing-home-modules -no-user-package-db -package-db /home/picca/.cabal/store/ghc-8.8.4/package.db -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/packagedb/ghc-8.8.4 -package-db /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/package.conf.inplace -package-id attoparsec-0.13.2.4-Ab3vFYnVhC6LY7sYuAbpTr -package-id base-4.13.0.0 -package-id containers-0.6.2.1 -package-id dimensional-1.3-C8v0k83E9Py18UKTdF1oLh -package-id exceptions-0.10.4-9CfD2hJyZLFIbks3iYGf0k -package-id filepath-1.4.2.1 -package-id hkl-0.1.0.0-inplace -package-id monad-logger-0.3.34-CJMMf2yR5GpALmIIglLyst -package-id monad-loops-0.4.3-9fN6QF5xEO8BUJUobxjHs -package-id optparse-applicative-0.15.1.0-GiY4uo4FBQRKuBqOktTXko -package-id pipes-4.3.14-KiHrcdQOQdo1w0hHviOVEE -package-id text-1.2.4.0 -package-id transformers-0.5.6.2 -package-id vector-0.12.1.2-C2W44iPdAFeHo4yLU081Gd -XHaskell2010 ./app/Binoculars.hs -o /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng -O2 -Wall -Werror -rtsopts -threaded -g -dcore-lint -debug -ddump-to-file -ddump-simpl -ddump-stg '-with-rtsopts=-N' -pgml gcc -optl-Wl,--allow-multiple-definition -optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive -optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive -hide-all-packages > Linking /home/picca/src/repo.or.cz/hkl/contrib/haskell/dist-newstyle/build/x86_64-linux/ghc-8.8.4/hkl-0.1.0.0/x/binoculars-ng/build/binoculars-ng/binoculars-ng ... > CallStack (from HasCallStack): > die', called at ./Distribution/Client/ProjectOrchestration.hs:1035:55 in main:Distribution.Client.ProjectOrchestration > cabal: Failed to build hkl-0.1.0.0-inplace-hkl-test. > > > the difference is that there is no link phase for the executable binary (it has only one file). > > I see no reference to TH during the compilation of this part of the code. (It is true thaht I use TH in the librarie). > > Cheers > > Fred -- brandon s allbery kf8nh allbery.b at gmail.com From frederic-emmanuel.picca at synchrotron-soleil.fr Mon Jan 10 13:30:50 2022 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Mon, 10 Jan 2022 14:30:50 +0100 (CET) Subject: [Haskell-cafe] strange link error In-Reply-To: <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: <1088473724.2654305.1641821450825.JavaMail.zimbra@synchrotron-soleil.fr> Ok, just by adding if flag(useHklDev) extra-libraries: hkl-binoculars extra-libraries: hkl in the library part and if flag(useHklDev) ghc-options: "-optl-Wl,--allow-multiple-definition" ghc-options: "-optl-Wl,--whole-archive,../../hkl/.libs/libhkl.a,--no-whole-archive" ghc-options: "-optl-Wl,--whole-archive,../../binoculars/libhkl-binoculars.a,--no-whole-archive" in the test part, I solved this issue. thanks for your help Fred From frederic-emmanuel.picca at synchrotron-soleil.fr Mon Jan 10 16:48:37 2022 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Mon, 10 Jan 2022 17:48:37 +0100 (CET) Subject: [Haskell-cafe] strange link error In-Reply-To: <1088473724.2654305.1641821450825.JavaMail.zimbra@synchrotron-soleil.fr> References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> <1088473724.2654305.1641821450825.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: <1388115622.2971010.1641833317114.JavaMail.zimbra@synchrotron-soleil.fr> Hello, In fact I changed my strategie and now I use cabal configure in order to gives the extra-lib-dirs and extra-include-dirs It works great for the build but When I try to run the program it end up with a can not found library libhkl.so.5 So my question is why theses extra-lib-dirs are not added to the LD_LIBRARY_PATH when we use cabal run and cabal test Cheers Frederic From mikolaj at well-typed.com Mon Jan 10 17:22:56 2022 From: mikolaj at well-typed.com (Mikolaj Konarski) Date: Mon, 10 Jan 2022 18:22:56 +0100 Subject: [Haskell-cafe] strange link error In-Reply-To: <1388115622.2971010.1641833317114.JavaMail.zimbra@synchrotron-soleil.fr> References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> <1088473724.2654305.1641821450825.JavaMail.zimbra@synchrotron-soleil.fr> <1388115622.2971010.1641833317114.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: So it works fine with `cabal run` and `cabal test` when the extra dirs are in .cabal file, but not fine when they are in the cabal.project.local file? There may or may not be a good reason for that. Could you search the cabal's issue tracker and either add to a ticket or create a new one? Thank you! On Mon, Jan 10, 2022 at 5:53 PM PICCA Frederic-Emmanuel wrote: > > Hello, In fact I changed my strategie and now I use > > cabal configure in order to gives the extra-lib-dirs and extra-include-dirs > > It works great for the build > > but When I try to run the program it end up with a can not found library libhkl.so.5 > > So my question is why theses extra-lib-dirs are not added to the LD_LIBRARY_PATH when we use > > cabal run > > and > > cabal test > > Cheers > > 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 frederic-emmanuel.picca at synchrotron-soleil.fr Mon Jan 10 17:26:15 2022 From: frederic-emmanuel.picca at synchrotron-soleil.fr (PICCA Frederic-Emmanuel) Date: Mon, 10 Jan 2022 18:26:15 +0100 (CET) Subject: [Haskell-cafe] strange link error In-Reply-To: References: <1817646551.2063950.1641804454934.JavaMail.zimbra@synchrotron-soleil.fr> <407825763.2375345.1641811851844.JavaMail.zimbra@synchrotron-soleil.fr> <1088473724.2654305.1641821450825.JavaMail.zimbra@synchrotron-soleil.fr> <1388115622.2971010.1641833317114.JavaMail.zimbra@synchrotron-soleil.fr> Message-ID: <1081535659.2997842.1641835575635.JavaMail.zimbra@synchrotron-soleil.fr> > So it works fine with `cabal run` and `cabal test` when the extra dirs are > in .cabal file, but not fine when they are in the cabal.project.local file? > There may or may not be a good reason for that. Could you > search the cabal's issue tracker and either add to a ticket > or create a new one? Thank you! No in fact the first success story was a mistake.. due to a local install of the library which was in the default search path of gcc. So now I need to wrap cabal test and cabal run binoculars-ng in order to set LD_LIBRARY_PATH= It seesm strage to me that this is required when we gives cabal configure extra-lib-dirs. cheers Fred From john at yourdigitalvoice.net Tue Jan 11 09:16:14 2022 From: john at yourdigitalvoice.net (John Sinclair) Date: Tue, 11 Jan 2022 22:16:14 +1300 Subject: [Haskell-cafe] [CFP closing soon!] Functional Conf 2022 Call for Proposals close 15 Jan Message-ID: Just 4 days remain to submit proposals for speaking at Functional Conf 2022. This is an online opportunity for you to contribute to Asia’s most vibrant functional programming conference. All selected speakers get a free ticket to the conference. Share your knowledge of Haskell and connect with programmers actively contributing to the development of FP languages, developers using it in their day-to-day programming and those just getting started on their FP journey. There’s something for everyone! At our last conference we featured keynotes from international guests Edward Kmett (Chairman, Haskell Core Libraries Committee), Michael Snoyman (VP Engineering at FP Complete) and Tony Morris (Sr. Software Engineer at Queensland FP Lab). Will you join us as a speaker this year? This year we are focusing on the themes of: - Applying FP - Applying FP sessions are targeted at Developers, who understand the basics of FP, maybe even practice some FP at work. Helping them understand how they can apply even more FP concepts more at work. - FP Bootcamp - FP Bootcamp is targeted at Developers, who want to kick start their FP journey. - Mastering FP - Mastering FP sessions are targeted at Developers, who already apply a decent amount of FP concepts at work. Developers, who want to go deeper and maybe even become a contributor to a FP language or library. Session Formats - Talks/Case-Studies (20 or 45 minutes) - Demos (20 or 45 minutes) - Experience Reports (20 minutes) - Hands-on workshop/tutorials (45 or 90 minutes) Proposal submission deadline: 15 January Learn more and submit your proposal: https://confng.in/qXN4WvpA -------------- next part -------------- An HTML attachment was scrubbed... URL: From anton.kholomiov at gmail.com Tue Jan 11 14:12:10 2022 From: anton.kholomiov at gmail.com (Anton Kholomiov) Date: Tue, 11 Jan 2022 17:12:10 +0300 Subject: [Haskell-cafe] [ANN] plutus-simple-model - unit test linrary for plutus with resource estimation Message-ID: Hi! I’d like to announce the unit test library plutus-simple-model for plutus that is a joy to use [1]. It’s simple and easy to grasp and it can estimate resource usage for TX (size and execution units). Main idea is to implement a simple blockchain model that updates UTXOs inside a pure State monad if TX is valid. To check TX cardano node functions are used so the check is the same as if node would check it and it produces useful stats for resource usage. Benefits comparing to EmulatorTrace to me: - I find resource usage stats are useful to know in production and this is missing in Emulator tests - EmulatorTrace approach makes it hard to query run-time information and with given lib it’s super easy - Having to define separate API and use lookups/constraints seems clumsy to me. It often leads to writing lots of boilerplate code. - it’s much faster to run I’ve tested it successfully in one project and using it for the second one. It has great docs and tutorials. Enjoy! I hope it will improve your testing experience with plutus. [1] plutus-simple-model https://github.com/mlabs-haskell/plutus-simple-model -------------- next part -------------- An HTML attachment was scrubbed... URL: From P.Achten at cs.ru.nl Tue Jan 11 17:14:06 2022 From: P.Achten at cs.ru.nl (Peter Achten) Date: Tue, 11 Jan 2022 18:14:06 +0100 Subject: [Haskell-cafe] [TFP'22] second call for papers: Trends in Functional Programming 2022 moved to March 17-18 online (together with TFPiE) Message-ID: ============== TFP 2022 =================== == MOVING TO ONLINE SYMPOSIUM, NEW DATES == =========================================== 23rd Symposium on Trends in Functional Programming 17-18 March, 2022 Online event https://trendsfp.github.io/index.html Due the pandemic, we have had to make TFP virtual this year. As a result, we've decided to push back the deadlines and conference date by a few weeks. In particular, the pre-symposium deadline for submitting the first version of your paper is now just after the ICFP deadline. == Important Dates == Submission deadline for draft papers                Monday 7th March, 2022 Notification for draft submissions                  Friday 11th March, 2022 Symposium dates                                     Thursday 17th - Friday 18th March, 2022 Submission deadline for post-symposium reviewing    Wednesday 6th April, 2022 Notification for post-symposium submissions         Friday 27th May, 2022 The Symposium on Trends in Functional Programming (TFP) is an international forum for researchers with interests in all aspects of functional programming, taking a broad view of current and future trends in the area. It aspires to be a lively environment for presenting the latest research results, and other contributions. == Scope == The symposium recognizes that new trends may arise through various routes. As part of the Symposium's focus on trends we therefore identify the following five article categories. High-quality articles are solicited in any of these categories: * Research Articles:    Leading-edge, previously unpublished research work * Position Articles:   On what new trends should or should not be * Project Articles:    Descriptions of recently started new projects * Evaluation Articles:    What lessons can be drawn from a finished project * Overview Articles:    Summarizing work with respect to a trendy subject Articles must be original and not simultaneously submitted for publication to any other forum. They may consider any aspect of functional programming: theoretical, implementation-oriented, or experience-oriented. Applications of functional programming techniques to other languages are also within the scope of the symposium. Topics suitable for the symposium include, but are not limited to: * Functional programming and multicore/manycore computing * Functional programming in the cloud * High performance functional computing * Extra-functional (behavioural) properties of functional programs * Dependently typed functional programming * Validation and verification of functional programs * Debugging and profiling for functional languages * Functional programming in different application areas:    security, mobility, telecommunications applications, embedded    systems, global computing, grids, etc. * Interoperability with imperative programming languages * Novel memory management techniques * Program analysis and transformation techniques * Empirical performance studies * Abstract/virtual machines and compilers for functional languages * (Embedded) domain specific languages * New implementation strategies * Any new emerging trend in the functional programming area If you are in doubt on whether your article is within the scope of TFP, please contact the TFP 2022 program chairs, Wouter Swierstra and Nicolas Wu. == Best Paper Awards == To reward excellent contributions, TFP awards a prize for the best paper accepted for the formal proceedings. TFP traditionally pays special attention to research students, acknowledging that students are almost by definition part of new subject trends. A student paper is one for which the authors state that the paper is mainly the work of students, the students are listed as first authors, and a student would present the paper. A prize for the best student paper is awarded each year. In both cases, it is the PC of TFP that awards the prize. In case the best paper happens to be a student paper, that paper will then receive both prizes. == Instructions to Author == Papers must be submitted at:    https://easychair.org/conferences/?conf=tfp22 Authors of papers have the choice of having their contributions formally reviewed either before or after the Symposium. == Post-symposium formal review process == Draft papers will receive minimal reviews and notification of acceptance for presentation at the symposium. Authors of draft papers will be invited to submit revised papers based on the feedback received at the symposium. A post-symposium refereeing process will then select a subset of these articles for formal publication. == Paper categories == Draft papers and papers submitted for formal review are submitted as extended abstracts (4 to 10 pages in length) or full papers (20 pages). The submission must clearly indicate which category it belongs to: research, position, project, evaluation, or overview paper. It should also indicate which authors are research students, and whether the main author(s) are students. A draft paper for which all authors are students will receive additional feedback by one of the PC members shortly after the symposium has taken place. == Format == Papers must be written in English, and written using the LNCS style. For more information about formatting please consult the Springer LNCS web site. == Program Committee == Guillaume Allais                University of St Andrews José Manuel Calderón Trilla     Galois, Inc. Stephen Chang                   University of Massachusetts Boston Matthew Flatt                   University of Utah Jeremy Gibbons                  University of Oxford Zhenjiang Hu                    Peking University Mauro Jaskelioff                CIFASIS / Universidad Nacional de Rosario Moa Johansson                   Chalmers University of Technology Shin-ya Katsumata               National Institute of Informatics Oleg Kiselyov                   Tohoku University Bas Lijnse                      Netherlands Defence Academy / Radboud University Nijmegen Kazutaka Matsuda                Tohoku University Nico Naus                       Virginia Tech Christine Rizkallah             University of New South Wales Alejandro Serrano               47 Degrees Amir Shaikhha                   Ecole Polytechnique Fédérale de Lausanne Aaron Stump                     University of Iowa Wouter Swierstra (Co-chair)     Utrecht University Baltasar Trancón Y Widemann     Semantics GmbH Nicolas Wu (Co-chair)           Imperial College London Ningning Xie                    University of Hong Kong From stefan.wehr at gmail.com Thu Jan 13 15:38:50 2022 From: stefan.wehr at gmail.com (Stefan Wehr) Date: Thu, 13 Jan 2022 16:38:50 +0100 Subject: [Haskell-cafe] Call for Participation: BOB 2022 (March 11, Berlin or online) Message-ID: ================================================================================ BOB 2022 Conference “What happens if we simply use what’s best?” March 11, 2022, Berlin or online 0100+UTC https://bobkonf.de/2022/ Program: https://bobkonf.de/2022/program.html Berlin or online? Fill out our survey: https://bobkonf.de/2022/onsite.html ================================================================================ BOB conference is a place for developers, architects, and decision-makers to explore technologies beyond the mainstream in software development and to find the best tools available to software developers today. Our goal is for all participants of BOB to return home with new insights that enable them to improve their own software development experience. The program features 14 talks and 8 tutorials on current topics: https://bobkonf.de/2022/program.html The subject range includes functional programming, effects, distributed programming, formal methods, generative art, event-driven systems, the human brain, Haskell, Python, Scala, Lua, Clojure, Erlang, Nix, and others. Derek Dreyer will give the keynote talk. NOTE: We will decide on January 17 whether BOB 2022 will take place on-site in Berlin or online. Either way, we are working towards fostering a lively exchange of exciting ideas and enabling meaningful social interactions. We're collecting feedback on the issue here: https://bobkonf.de/2022/onsite.html If you're interested in BOB, please take a minute to fill the survey linked above! Registration will also open on January 17, once the decision for on-site or online has been made. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dyaitskov at gmail.com Thu Jan 13 22:12:24 2022 From: dyaitskov at gmail.com (Daneel Yaitskov) Date: Thu, 13 Jan 2022 17:12:24 -0500 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? Message-ID: Cafe, There is a group of GHC extensions and complementary classes to make writing Haskell code a bit sweeter such as: - {} - Num (fromIntegral) - OverloadedStrings - IsString - OverloadedLists - IsList So I have an inductive question - why there is no OverloadedTuples? I haven't found a discussion thread about this topic. I could imagine following tuple syntax interpretation: {-# LANGUAGE OverloadedTuples #-} data Foo = FooA Int String | FooB String Foo deriving (Show, Eq, IsTuple) mkFoo :: Foo mkFoo = (1, "hello") mkFoo2 :: Foo mkFoo = ("abc", (1, "hello")) Sometimes expected type name is known without data constructor. So such expression is more concise. -- Best regards, Daniil Iaitskov -------------- next part -------------- An HTML attachment was scrubbed... URL: From lists at richarde.dev Thu Jan 13 23:13:56 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Thu, 13 Jan 2022 23:13:56 +0000 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: Message-ID: <010f017e55b81dbe-b79fbf8f-7459-4910-ba60-663a0e1d76f5-000000@us-east-2.amazonses.com> We could potentially have this. It reminds me of Agda's record syntax, where you can construct any record (which is like your tuple) with the keyword `record`. Is it worth having yet another feature in the language? I'm not sure, myself. Richard > On Jan 13, 2022, at 5:12 PM, Daneel Yaitskov wrote: > > Cafe, > > There is a group of GHC extensions and complementary classes > to make writing Haskell code a bit sweeter such as: > - {} - Num (fromIntegral) > - OverloadedStrings - IsString > - OverloadedLists - IsList > > So I have an inductive question - why there is no OverloadedTuples? > I haven't found a discussion thread about this topic. > > I could imagine following tuple syntax interpretation: > > {-# LANGUAGE OverloadedTuples #-} > > data Foo = FooA Int String | FooB String Foo deriving (Show, Eq, IsTuple) > > mkFoo :: Foo > mkFoo = (1, "hello") > > mkFoo2 :: Foo > mkFoo = ("abc", (1, "hello")) > > Sometimes expected type name is known without data constructor. > So such expression is more concise. > > > > -- > > Best regards, > Daniil Iaitskov > > > > _______________________________________________ > 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 allbery.b at gmail.com Thu Jan 13 23:19:29 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Thu, 13 Jan 2022 18:19:29 -0500 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: <010f017e55b81dbe-b79fbf8f-7459-4910-ba60-663a0e1d76f5-000000@us-east-2.amazonses.com> References: <010f017e55b81dbe-b79fbf8f-7459-4910-ba60-663a0e1d76f5-000000@us-east-2.amazonses.com> Message-ID: I'm not sure I like the idea of Haskell trying to guess a constructor to use from a tuple. What happens if multiple constructors could match, for one? On Thu, Jan 13, 2022 at 6:17 PM Richard Eisenberg wrote: > > We could potentially have this. It reminds me of Agda's record syntax, where you can construct any record (which is like your tuple) with the keyword `record`. > > Is it worth having yet another feature in the language? I'm not sure, myself. > > Richard > > On Jan 13, 2022, at 5:12 PM, Daneel Yaitskov wrote: > > Cafe, > > There is a group of GHC extensions and complementary classes > to make writing Haskell code a bit sweeter such as: > - {} - Num (fromIntegral) > - OverloadedStrings - IsString > - OverloadedLists - IsList > > So I have an inductive question - why there is no OverloadedTuples? > I haven't found a discussion thread about this topic. > > I could imagine following tuple syntax interpretation: > > {-# LANGUAGE OverloadedTuples #-} > > data Foo = FooA Int String | FooB String Foo deriving (Show, Eq, IsTuple) > > mkFoo :: Foo > mkFoo = (1, "hello") > > mkFoo2 :: Foo > mkFoo = ("abc", (1, "hello")) > > Sometimes expected type name is known without data constructor. > So such expression is more concise. > > > > -- > > Best regards, > Daniil Iaitskov > > > > _______________________________________________ > 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. -- brandon s allbery kf8nh allbery.b at gmail.com From keith.wygant at gmail.com Fri Jan 14 00:33:47 2022 From: keith.wygant at gmail.com (Keith) Date: Fri, 14 Jan 2022 00:33:47 +0000 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: <010f017e55b81dbe-b79fbf8f-7459-4910-ba60-663a0e1d76f5-000000@us-east-2.amazonses.com> Message-ID: <47B46888-8796-4839-8550-71118E6050FB@gmail.com> `(,) :: forall a b c. (IsPair c, Fst c ~ a, Snd c ~ b)=> a → b → c` Might be nice syntax for `data StrictPair a b = StrictPair !a !b`. — Sent from my phone with K-9 Mail. On 13 January 2022 23:19:29 UTC, Brandon Allbery wrote: >I'm not sure I like the idea of Haskell trying to guess a constructor >to use from a tuple. What happens if multiple constructors could >match, for one? > >On Thu, Jan 13, 2022 at 6:17 PM Richard Eisenberg wrote: >> >> We could potentially have this. It reminds me of Agda's record syntax, where you can construct any record (which is like your tuple) with the keyword `record`. >> >> Is it worth having yet another feature in the language? I'm not sure, myself. >> >> Richard >> >> On Jan 13, 2022, at 5:12 PM, Daneel Yaitskov wrote: >> >> Cafe, >> >> There is a group of GHC extensions and complementary classes >> to make writing Haskell code a bit sweeter such as: >> - {} - Num (fromIntegral) >> - OverloadedStrings - IsString >> - OverloadedLists - IsList >> >> So I have an inductive question - why there is no OverloadedTuples? >> I haven't found a discussion thread about this topic. >> >> I could imagine following tuple syntax interpretation: >> >> {-# LANGUAGE OverloadedTuples #-} >> >> data Foo = FooA Int String | FooB String Foo deriving (Show, Eq, IsTuple) >> >> mkFoo :: Foo >> mkFoo = (1, "hello") >> >> mkFoo2 :: Foo >> mkFoo = ("abc", (1, "hello")) >> >> Sometimes expected type name is known without data constructor. >> So such expression is more concise. >> >> >> >> -- >> >> Best regards, >> Daniil Iaitskov >> >> >> >> _______________________________________________ >> 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. > > > >-- >brandon s allbery kf8nh >allbery.b at gmail.com >_______________________________________________ >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 jeffbrown.the at gmail.com Fri Jan 14 00:50:02 2022 From: jeffbrown.the at gmail.com (Jeffrey Brown) Date: Thu, 13 Jan 2022 19:50:02 -0500 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: Message-ID: You can get very close -- specifically, to within two extra characters -- to the brevity you're imagining without introducing any new extensions: data Foo = Foo Int Int deriving (Show) f :: (Int, Int) -> Foo f = uncurry Foo g :: Int -> Int -> Foo g = Foo `f` is almost what you wanted. `g` will in many situations be terser. On Thu, Jan 13, 2022 at 5:12 PM Daneel Yaitskov wrote: > Cafe, > > There is a group of GHC extensions and complementary classes > to make writing Haskell code a bit sweeter such as: > - {} - Num (fromIntegral) > - OverloadedStrings - IsString > - OverloadedLists - IsList > > So I have an inductive question - why there is no OverloadedTuples? > I haven't found a discussion thread about this topic. > > I could imagine following tuple syntax interpretation: > > {-# LANGUAGE OverloadedTuples #-} > > data Foo = FooA Int String | FooB String Foo deriving (Show, Eq, IsTuple) > > mkFoo :: Foo > mkFoo = (1, "hello") > > mkFoo2 :: Foo > mkFoo = ("abc", (1, "hello")) > > Sometimes expected type name is known without data constructor. > So such expression is more concise. > > > > -- > > Best regards, > Daniil Iaitskov > > > > _______________________________________________ > 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. -- Jeff Brown | Jeffrey Benjamin Brown LinkedIn | Github | Twitter | Facebook -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Fri Jan 14 01:02:38 2022 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Thu, 13 Jan 2022 20:02:38 -0500 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: Message-ID: On Thu, Jan 13, 2022 at 07:50:02PM -0500, Jeffrey Brown wrote: > You can get very close -- specifically, to within two extra characters -- > to the brevity you're imagining without introducing any new extensions: > > data Foo = Foo Int Int > deriving (Show) > > f :: (Int, Int) -> Foo > f = uncurry Foo > > g :: Int -> Int -> Foo > g = Foo {-# LANGUAGE PatternSynonyms #-} pattern F :: Int -> Int -> Foo pattern F f s = Foo f s Which abbreviates a frequently used constructor, and works in pattern matches too. λ> case F 4 "2" of { F x y -> show x ++ y } "42" But the original question is really about logical completeness of overloading primitives, not about work-arounds, so bottom line I too don't think that overloading tuples is justified, since this breaks extensibility if constructor type signatures later become ambiguous, I don't think the idea has sufficient merit. -- Viktor. From sekiyama at nii.ac.jp Fri Jan 14 12:55:09 2022 From: sekiyama at nii.ac.jp (Taro Sekiyama) Date: Fri, 14 Jan 2022 21:55:09 +0900 Subject: [Haskell-cafe] Postdoc positions on Formal Verification for Zero-Trust IoT Systems at Kyoto University and National Institute of Informatics (NII), Japan Message-ID: <13a9d349-b7da-a970-0f72-912f66945569@nii.ac.jp> [Please distribute, apologies for multiple postings.] Dear All, We are seeking a few postdoc researchers, who works for a project “Zero-Trust IoT Systems by Collaboration of Formal Verification and System Software” by Japan Science and Technology Agency. We'd be grateful if you could spread the word to interested candidates. * Project Description The project aims at the construction of formally verified secure IoT systems that follow the concept of “zero trust architecture”, dubbed ZT-IoT systems. It consists of four research teams and two teams, led by Atsushi Igarashi, Kyoto University, Japan and Taro Sekiyama, National Institute of Informatics, Japan (NII) are investigating applications of formal verification or programming language techniques to the construction of secure IoT systems. The main research topic of Igarashi’s team is centered around the design and theory of security policy engines for ZT-IoT systems, inclucing the design of a language to describe security policies and policy enforcement algorithms and the techniques for verifying policy enforcement algorithms against given security policies. Other team members are Kohei Suenaga and Masaki Waga at Kyoto University. The main research topic of Sekiyama’s team is centered around techniques for monitoring and intervention for ZT-IoT systems. Other team members include Ichiro Hasuo and Shin-ya Katsumata at NII. Although the two teams are based in different places, we collaborate closely with each other. The appointment can start as early as April 2022 (the starting date is negotiable). The contract will initially run until the end of March 2023, with the possibility of annual renewal until the end of the project, which is March 2027 at maximum. Salary will be about 360,000–550,000 JPY/month. Applicants should have a Ph.D in computer science or related fields, and have a strong background in formal verification and/or programming language theory. Due to the project’s nature, they are required to have strong interests in applying theory to practice; they should also be (self-)motivated, dedicated, and able to work both independently and collaboratively. Strong communication skills in oral and written English are required. * Workplace Members of Igarashi’s team will work at Kyoto University, Kyoto, Japan and members of Sekiyama’s team will work at NII, Tokyo, Japan. (Living costs in Japan are not very high nowadays. An estimate is found here https://www.internations.org/go/moving-to-japan/living/the-cost-of-living-in-japan#:~:text=A%20single%20person%20living%20in,will%20see%20that%20number%20tripled and we find rent can be cheaper than the cited amount.) * Applications and inquiries Inquiries can be sent to application-zt-iot [at] fos.kuis.kyoto-u.ac.jp, with the subject CREST Job Inquiry. Feel free to ask us any questions on relevance, topics, compensation, etc. We will reply when we see enough relevance. Applications should be made electronically via the following JREC-IN Portal web sites. NII: https://jrecin.jst.go.jp/seek/SeekJorDetail?fn=3&ln=1&id=D122010021&ln_jor=1 Kyoto: https://jrecin.jst.go.jp/seek/SeekJorDetail?fn=3&ln=1&id=D121122219&ln_jor=1 Please upload a pdf including - your brief CV, - short description of research interests (can be very informal and short), - the list of papers (a dblp or Google scholar link will do, for example), - a couple of representative papers (in pdf), and - (preferably) the contact of two references. We will contact you for further material and interview, provided that we find sufficient relevance in your application. Starting dates are negotiable. The positions will remain open until filled. Many thanks, Taro. From elenam at morris.umn.edu Fri Jan 14 14:03:21 2022 From: elenam at morris.umn.edu (Elena Machkasova) Date: Fri, 14 Jan 2022 09:03:21 -0500 Subject: [Haskell-cafe] TFPIE 2022: moving to online and extension to Feb 7th Message-ID: Due to rescheduling of the Lambda Days because of COVID, TFPIE, together with TFP, will be held virtually on March 16th 2022, together with TFP which will be held on March 17-18. There is an optional opportunity to present at the Lambda Days July 28-29 2022 in addition to the virtual presentation in March. Updated TFPIE 2022 Call for papers: https://wiki.tfpie.science.ru.nl/TFPIE2022 The submission deadline is extended to February 7th 2022. TFPIE 2022 welcomes submissions describing techniques used in the classroom, tools used in and/or developed for the classroom and any creative use of functional programming (FP) to aid education in or outside Computer Science. Topics of interest include, but are not limited to: FP and beginning CS students FP and Computational Thinking FP and Artificial Intelligence FP in Robotics FP and Music Advanced FP for undergraduates FP in graduate education Engaging students in research using FP FP in Programming Languages FP in the high school curriculum FP as a stepping stone to other CS topics FP and Philosophy The pedagogy of teaching FP FP and e-learning: MOOCs, automated assessment etc. Best Lectures - more details below In addition to papers, we are requesting best lecture presentations. What's your best lecture topic in an FP related course? Do you have a fun way to present FP concepts to novices or perhaps an especially interesting presentation of a difficult topic? In either case, please consider sharing it. Best lecture topics will be selected for presentation based on a short abstract describing the lecture and its interest to TFPIE attendees. The length of the presentation should be comparable to that of a paper. In addition, the speaker can provide commentary on effectiveness or student feedback. Submissions Potential presenters are invited to submit an extended abstract (4-6 pages) or a draft paper (up to 20 pages) in EPTCS style. The authors of accepted presentations will have their preprints and their slides made available on the workshop's website. Papers and abstracts can be submitted via easychair at the following link: https://easychair.org/conferences/?conf=tfpie2022 After the workshop, presenters are invited to submit (a revised version of) their article for the formal review. The PC will select the best articles for publication in the Electronic Proceedings in Theoretical Computer Science (EPTCS). Articles rejected for presentation and extended abstracts will not be formally reviewed by the PC. Important Dates (updated) Submission deadline: *February 7th* 2022, Anywhere on Earth. Notification: *February 11th* 2022 (Note: earlier submissions will receive earlier response) TFPIE Registration Deadline: TBA Workshop: *March 16* 2022 Submission for formal review: *April 29th* 2022, Anywhere on Earth. Notification of full article: June 1st 2022 Camera ready: July 1st 2022 Program Committee Peter Achten, Radboud University, Netherlands Stephen Chang, University of Massachusetts Boston, USA John Hughes, Chalmers University of Technology, Sweden Elena Machkasova (Chair) - University of Minnesota Morris, USA Kristina Sojakova - INRIA, Paris, France Melinda Tóth, Eötvös Loránd University, Budapest, Hungary Keynote speaker: Our keynote talk is "The perfect Functional Programming course" by Peter Achten. Registration information: TFPIE will take place virtually on March 16 2022, together with TFP which will be held on March 17-18. Registration information will be announced shortly. There is no registration fee. Registration and online attendance are mandatory for at least one author of every paper that is presented at the workshop. Only papers that have been presented at TFPIE may be submitted to the post-reviewing process. -- Dr. Elena Machkasova Associate Professor of Computer Science Division of Science and Mathematics University of Minnesota, Morris Office: Sci 2325 (320) 589-6308 http://cda.morris.umn.edu/~elenam/ Pronouns: she/her/hers or any other -------------- next part -------------- An HTML attachment was scrubbed... URL: From tgphelps50 at gmail.com Sat Jan 15 14:32:27 2022 From: tgphelps50 at gmail.com (Terry Phelps) Date: Sat, 15 Jan 2022 09:32:27 -0500 Subject: [Haskell-cafe] Newbie question Message-ID: I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough: Make a function 'last' that returns the last element of a non-empty list. After struggling a while, I looked at the answer: last = head . reverse. I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote: last [] = [] (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added: last [x] = x And I checked the type: :t last last:: [a] -> [a] Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote: last (x:y:xs) = last (y:xs) I ran it: Prelude> last [1,2] *** Exception: :2:1-27: Non-exhaustive patterns in function last What the heck is the problem? I've covered every possible list, haven't I? Stranger yet, I check the type again: Prelude> :t last last :: [a] -> t The type has changed. And I don't understand what it means. What's the 't'? I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change. Someone help, please. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jerzy.karczmarczuk at unicaen.fr Sat Jan 15 14:40:16 2022 From: jerzy.karczmarczuk at unicaen.fr (Jerzy Karczmarczuk) Date: Sat, 15 Jan 2022 15:40:16 +0100 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: <0af206f6-2c00-1c43-4e8b-305bb62dba32@unicaen.fr> Le 15/01/2022 à 15:32, Terry Phelps a écrit : ... > *last [] = [] * > (Yes, I know that's not a non-empty list, but I don't want ghci > whining about non-exhaustive patterns). Then I added: > > *last [x] = x* Please notice that these two clauses are type-incoherent, unless *x* is a list Jerzy Karczmarczuk -- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus -------------- next part -------------- An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Sat Jan 15 14:43:05 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Sat, 15 Jan 2022 09:43:05 -0500 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements. On Sat, Jan 15, 2022 at 9:33 AM Terry Phelps wrote: > > I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough: > > Make a function 'last' that returns the last element of a non-empty list. > > After struggling a while, I looked at the answer: last = head . reverse. > I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote: > > last [] = [] > (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added: > > last [x] = x > And I checked the type: > :t last > last:: [a] -> [a] > > Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote: > > last (x:y:xs) = last (y:xs) > > I ran it: > > Prelude> last [1,2] > *** Exception: :2:1-27: Non-exhaustive patterns in function last > > What the heck is the problem? I've covered every possible list, haven't I? > > Stranger yet, I check the type again: > > Prelude> :t last > last :: [a] -> t > > The type has changed. And I don't understand what it means. What's the 't'? > > I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change. > > Someone help, please. > _______________________________________________ > 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. -- brandon s allbery kf8nh allbery.b at gmail.com From allbery.b at gmail.com Sat Jan 15 14:49:25 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Sat, 15 Jan 2022 09:49:25 -0500 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: Actually, I'm going to correct that; I misread. I suspect your real problem is you entered those on separate lines in ghci, and each one redefines the previous one instead of augmenting it because ghci can't know you're going to continue the definition. Either use multi-line input mode (:{ and :}) or enter them all on one line with semicolons in place of newlines. On Sat, Jan 15, 2022 at 9:43 AM Brandon Allbery wrote: > > You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements. > > On Sat, Jan 15, 2022 at 9:33 AM Terry Phelps wrote: > > > > I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough: > > > > Make a function 'last' that returns the last element of a non-empty list. > > > > After struggling a while, I looked at the answer: last = head . reverse. > > I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote: > > > > last [] = [] > > (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added: > > > > last [x] = x > > And I checked the type: > > :t last > > last:: [a] -> [a] > > > > Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote: > > > > last (x:y:xs) = last (y:xs) > > > > I ran it: > > > > Prelude> last [1,2] > > *** Exception: :2:1-27: Non-exhaustive patterns in function last > > > > What the heck is the problem? I've covered every possible list, haven't I? > > > > Stranger yet, I check the type again: > > > > Prelude> :t last > > last :: [a] -> t > > > > The type has changed. And I don't understand what it means. What's the 't'? > > > > I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change. > > > > Someone help, please. > > _______________________________________________ > > 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. > > > > -- > brandon s allbery kf8nh > allbery.b at gmail.com -- brandon s allbery kf8nh allbery.b at gmail.com From jerzy.karczmarczuk at unicaen.fr Sat Jan 15 14:54:06 2022 From: jerzy.karczmarczuk at unicaen.fr (Jerzy Karczmarczuk) Date: Sat, 15 Jan 2022 15:54:06 +0100 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: Le 15/01/2022 à 15:43, Brandon Allbery a écrit : > You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements. No, [1,2] === 1:(2:[]) But my own answer was incomplete. I suspect that there is a confusion because T.P. might hava a conflict between tha Prelude last and his own... Anyway, skip this : last [] = []  and change the name "last" to a private one. Jerzy Karczmarczuk -- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Sat Jan 15 14:56:29 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Sat, 15 Jan 2022 14:56:29 +0000 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: On Sat, Jan 15, 2022 at 09:32:27AM -0500, Terry Phelps wrote: > last [] = [] > (Yes, I know that's not a non-empty list, but I don't want ghci whining > about non-exhaustive patterns). Then I added: > > last [x] = x > And I checked the type: > :t last > last:: [a] -> [a] > > Yes, that looks right. There seems to be only one other case: 2 or more > elements. So I wrote: > > last (x:y:xs) = last (y:xs) The first problem is that you've defined three different functions, each overriding the next Prelude> foo s = "Hello " ++ s Prelude> foo s = "Goodbye " ++ s Prelude> foo "Tom" "Goodbye Tom" I suggest putting the functions in a source file, say "test.hs" and then loading it in GHCi instead. I also suggest calling your function "mylast" because Prelude already exports a function called "last": % cat test.hs mylast [] = [] mylast [x] = x mylast (x:y:xs) = mylast (y:xs) % ghci ... Prelude> :l test.hs [1 of 1] Compiling Main ( test.hs, interpreted ) Ok, one module loaded. *Main> :t mylast mylast :: [[a]] -> [a] *Main> mylast [[1,2], [3,4]] [3,4] It kind of does what you want, but not quite. That's the next problem for you to solve! Good luck and enjoy. Tom From raoknz at gmail.com Sun Jan 16 10:31:59 2022 From: raoknz at gmail.com (Richard O'Keefe) Date: Sun, 16 Jan 2022 23:31:59 +1300 Subject: [Haskell-cafe] Newbie question In-Reply-To: References: Message-ID: The definition last [] = [] was a bad move. Warnings about unhandled alternatives are only that, WARNINGS. Something like this is quite definitely wrong. We want last [1,2,3] ===> 3 but last [] = [] says that last can only return lists. It's OK to say "this is not defined". It's OK to say "this is an error case". It's not OK to make stuff up that does not fit. last [] = undefined last (x:xs) = last' x xs or last [] = error "last []" last (x:xs) = last' x xs let you assure the compiler (and your readers) that you *have* considered this case; you didn't just forget about it. They also do not constrain the result type in any way, so they don't interfere with the rest of the definition. The meaning of last' x xs is "last' x xs is the last element of [x]++xs" and you can figure that out for yourself with a simple case analysis on xs. A hint on reading exercises in functional programming books: "make a function F that ..." almost NEVER means "make a function F that ... without even thinking about introducing any helper functions." When defining last, introducing last' is OK. You can make it local if you want: last (x:xs) = last' x xs where last' x (y:ys) = ... last' x [] = ... last [] = error "last []" although you don't need to. -------------- next part -------------- An HTML attachment was scrubbed... URL: From carter.schonwald at gmail.com Mon Jan 17 13:08:15 2022 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Mon, 17 Jan 2022 08:08:15 -0500 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: Message-ID: In some respects, there’s another path: further generalizing overloaded lists with the right machinery for list syntax to support hlists and sized lists! I prototyped out a possible type class for this that predates pattern synonyms and I believe it could be made even nicer with pattern synonyms https://github.com/cartazio/HetList/blob/master/HetList.hs Here’s the example code above! On Thu, Jan 13, 2022 at 8:06 PM Viktor Dukhovni wrote: > On Thu, Jan 13, 2022 at 07:50:02PM -0500, Jeffrey Brown wrote: > > You can get very close -- specifically, to within two extra characters -- > > to the brevity you're imagining without introducing any new extensions: > > > > data Foo = Foo Int Int > > deriving (Show) > > > > f :: (Int, Int) -> Foo > > f = uncurry Foo > > > > g :: Int -> Int -> Foo > > g = Foo > > {-# LANGUAGE PatternSynonyms #-} > > pattern F :: Int -> Int -> Foo > pattern F f s = Foo f s > > Which abbreviates a frequently used constructor, and works in pattern > matches too. > > λ> case F 4 "2" of { F x y -> show x ++ y } > "42" > > But the original question is really about logical completeness of > overloading primitives, not about work-arounds, so bottom line I too > don't think that overloading tuples is justified, since this breaks > extensibility if constructor type signatures later become ambiguous, I > don't think the idea has sufficient merit. > > -- > Viktor. > _______________________________________________ > 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 Mon Jan 17 13:44:14 2022 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Mon, 17 Jan 2022 15:44:14 +0200 Subject: [Haskell-cafe] why OverloadedTuples extension is missing? In-Reply-To: References: Message-ID: If you want "completeness" for "overloaded things", I think you might be interested in this - https://github.com/phadej/overloaded Not sure if it has OverloadedTuples, but it's in the same spirit, and could probably be extended to have them. On Mon, Jan 17, 2022 at 3:09 PM Carter Schonwald wrote: > In some respects, there’s another path: further generalizing overloaded > lists with the right machinery for list syntax to support hlists and sized > lists! > > I prototyped out a possible type class for this that predates pattern > synonyms and I believe it could be made even nicer with pattern synonyms > > https://github.com/cartazio/HetList/blob/master/HetList.hs > > Here’s the example code above! > > On Thu, Jan 13, 2022 at 8:06 PM Viktor Dukhovni > wrote: > >> On Thu, Jan 13, 2022 at 07:50:02PM -0500, Jeffrey Brown wrote: >> > You can get very close -- specifically, to within two extra characters >> -- >> > to the brevity you're imagining without introducing any new extensions: >> > >> > data Foo = Foo Int Int >> > deriving (Show) >> > >> > f :: (Int, Int) -> Foo >> > f = uncurry Foo >> > >> > g :: Int -> Int -> Foo >> > g = Foo >> >> {-# LANGUAGE PatternSynonyms #-} >> >> pattern F :: Int -> Int -> Foo >> pattern F f s = Foo f s >> >> Which abbreviates a frequently used constructor, and works in pattern >> matches too. >> >> λ> case F 4 "2" of { F x y -> show x ++ y } >> "42" >> >> But the original question is really about logical completeness of >> overloading primitives, not about work-arounds, so bottom line I too >> don't think that overloading tuples is justified, since this breaks >> extensibility if constructor type signatures later become ambiguous, I >> don't think the idea has sufficient merit. >> >> -- >> Viktor. >> _______________________________________________ >> 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 sgf.dma at gmail.com Mon Jan 17 15:49:45 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Mon, 17 Jan 2022 18:49:45 +0300 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> Message-ID: On 1/3/22 5:26 PM, Richard Eisenberg wrote: > >> And does the error: >> >> coerce-existential-with-type-level-maybe.lhs:22:3: error: >> • Type variable ‘t’ is mentioned in the RHS, >> but not bound on the LHS of the family instance >> • In the type instance declaration for ‘ToType’ >> In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ >> | >> 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where >> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... >> >> when i try to apply 'Nothing to @Type instead of @t occurs, because >> full form of associated type family is >> >> type ToType ('Nothing @Type) = t >> >> and variable 't' becomes unbound? > > I wouldn't quite say t is unbound there -- it refers to the t in the instance head. What's more troublesome is that, when GHC is trying to reduce `ToType (Nothing @Type)`, it has no way of knowing what `t` is. This is why GHC requires that all variables mentioned in the RHS of an associated type equation are also mentioned on the left. > Hi, Richard. I thought, that my 'FromTypeMaybe' works, but it turns out not always. So, to recap: > {-# LANGUAGE DataKinds #-} > {-# LANGUAGE RankNTypes #-} > {-# LANGUAGE KindSignatures #-} > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE TypeOperators #-} > {-# LANGUAGE PolyKinds #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE GADTs #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE FlexibleContexts #-} > > import Data.Kind > import Data.Proxy > import Unsafe.Coerce > import qualified GHC.Types as GHC.Types > > class FromTypeMaybe k where > type ToType k > fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) > instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where > --type ToType 'Nothing = GHC.Types.Any > type ToType 'Nothing = t > fromTypeMaybe f _ x = Nothing > instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where > type ToType ('Just t) = t > fromTypeMaybe f _ x = Just (f x) then i've written a little more: > type MaybeHead :: [t] -> Maybe t > type family MaybeHead ts where > MaybeHead '[] = 'Nothing > MaybeHead (x ': xs) = 'Just x > > type Tail:: [t] -> [t] > type family Tail ts where > Tail '[] = '[] > Tail (x ': xs) = xs > > data AnyData where > AnyData :: a -> AnyData > > unAny :: AnyData -> t > unAny (AnyData x) = unsafeCoerce x > > insertAny :: t -> [AnyData] -> [AnyData] > insertAny x zs = AnyData x : zs > > headAny > :: forall ts > . FromTypeMaybe (MaybeHead ts) > => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) > headAny _ [] = Nothing > headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x And now it works, when type-level list is explicitly specified, like: *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] Nothing *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] Just 1 *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] Just 1 but if i use 'Tail' type-function first, it works only in two cases: for list with 2 or more elements *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] :: Maybe Int *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] Just 1 and empty list *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe t *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] Nothing But for list with 1 element it does not work *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :246:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it I think, that understand the problem, but yet don't know how to fix it. If i evaluate types, i get for 2-elements list *Main> :k! Tail '[Bool, Int] Tail '[Bool, Int] :: [*] = '[Int] *Main> :k! MaybeHead (Tail '[Bool, Int]) MaybeHead (Tail '[Bool, Int]) :: Maybe * = 'Just Int *Main> :k! ToType (MaybeHead (Tail '[Bool, Int])) ToType (MaybeHead (Tail '[Bool, Int])) :: * = Int for 1-element list *Main> :k! Tail '[Bool] Tail '[Bool] :: [*] = '[] *Main> :k! MaybeHead (Tail '[Bool]) MaybeHead (Tail '[Bool]) :: Maybe * = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = * and for empty list *Main> :k! Tail '[] Tail '[] :: [t] = '[] *Main> :k! MaybeHead (Tail '[]) MaybeHead (Tail '[]) :: Maybe t = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any Thus, for 1-element case in type-family 'Tail' type-of-type variable t gets instantiated to '*', because there is one element in list ('Bool' in the example) and its type (kind) is '*'. Then this type '*' goes through 'MaybeHead' and i get ('Nothing :: Maybe *), and type variable t in 'FromTypeMaybe' instance head also gets instantiated to '*'. And then it's just substituted in 'ToType' RHS. And i end up looking for (Show *) instance. In the empty list case, though, type-of-type variable 't' from 'Tail' remains as type variable till the end. But then (for some reason) GHC replaces it with 'GHC.Types.Any' and (yet more strangely) manages to find 'Show' instances for 'GHC.Types.Any'. When i've tried to check may understanding and changed 'Tail' type to type Tail :: [*] -> [*] the empty list case behaves like the 1-element case before: *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = * *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :309:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it and (not surprisingly) does not work. On the other hand, if i explicitly assign 'GHC.Types.Any' as 'ToType k' RHS in 'Nothing instance instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any then the 1-element case seems to become the same as the (working) empty list case from before *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = GHC.Types.Any *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any but GHC still can't find 'Show GHC.Types.Any' instance: *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :327:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘print’ There are instances for similar types: instance Show base-4.14.3.0:Data.Semigroup.Internal.Any -- Defined in ‘base-4.14.3.0:Data.Semigroup.Internal’ • In a stmt of an interactive GHCi command: print it *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :328:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘print’ There are instances for similar types: instance Show base-4.14.3.0:Data.Semigroup.Internal.Any -- Defined in ‘base-4.14.3.0:Data.Semigroup.Internal’ • In a stmt of an interactive GHCi command: print it Well, probably, the problem is that i don't understand what is 'GHC.Types.Any' and how GHC finds 'Show' instance for it ('Any types' notes in GHC.Builtin.Types does not explain much; probably, i need to read the book further instead..) And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) instance. Thanks. From sgf.dma at gmail.com Tue Jan 18 13:10:02 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Tue, 18 Jan 2022 16:10:02 +0300 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> Message-ID: <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> On 1/17/22 6:49 PM, Dmitriy Matrosov wrote: > >> {-# LANGUAGE DataKinds #-} >> {-# LANGUAGE RankNTypes #-} >> {-# LANGUAGE KindSignatures #-} >> {-# LANGUAGE TypeApplications #-} >> {-# LANGUAGE TypeOperators #-} >> {-# LANGUAGE PolyKinds #-} >> {-# LANGUAGE TypeFamilies #-} >> {-# LANGUAGE GADTs #-} >> {-# LANGUAGE StandaloneKindSignatures #-} >> {-# LANGUAGE ScopedTypeVariables #-} >> {-# LANGUAGE FlexibleContexts #-} >> >> import Data.Kind >> import Data.Proxy >> import Unsafe.Coerce >> import qualified GHC.Types as GHC.Types >> >> class FromTypeMaybe k where >>     type ToType k >>     fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) > >> instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where >>     --type ToType 'Nothing = GHC.Types.Any >>     type ToType 'Nothing = t >>     fromTypeMaybe f _ x = Nothing > >> instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where >>     type ToType ('Just t) = t >>     fromTypeMaybe f _ x = Just (f x) > > then i've written a little more: > >> type MaybeHead :: [t] -> Maybe t >> type family MaybeHead ts where >>     MaybeHead '[] = 'Nothing >>     MaybeHead (x ': xs) = 'Just x >> >> type Tail:: [t] -> [t] >> type family Tail ts where >>     Tail '[] = '[] >>     Tail (x ': xs) = xs >> >> data AnyData where >>     AnyData :: a -> AnyData >> >> unAny :: AnyData -> t >> unAny (AnyData x) = unsafeCoerce x >> >> insertAny :: t -> [AnyData] -> [AnyData] >> insertAny x zs = AnyData x : zs >> >> headAny >>     :: forall ts >>     . FromTypeMaybe (MaybeHead ts) >>     => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) >> headAny _ [] = Nothing >> headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x > > And now it works, when type-level list is explicitly specified, like: > >     *Main> headAny (Proxy @'[]) $  insertAny 1 $ insertAny True [] >     Nothing >     *Main> headAny (Proxy @'[Int]) $  insertAny 1 $ insertAny True [] >     Just 1 >     *Main> headAny (Proxy @'[Int, Bool]) $  insertAny 1 $ insertAny True [] >     Just 1 > > but if i use 'Tail' type-function first, it works only in two cases: > > for list with 2 or more elements > >     *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $  insertAny 1 $ insertAny True [] >     headAny (Proxy @(Tail '[Bool, Int])) $  insertAny 1 $ insertAny True [] >       :: Maybe Int >     *Main> headAny (Proxy @(Tail '[Bool, Int])) $  insertAny 1 $ insertAny True [] >     Just 1 > > and empty list > >     *Main> :t headAny (Proxy @(Tail '[])) $  insertAny 1 $ insertAny True [] >     headAny (Proxy @(Tail '[])) $  insertAny 1 $ insertAny True [] >       :: Maybe t >     *Main> headAny (Proxy @(Tail '[])) $  insertAny 1 $ insertAny True [] >     Nothing > > But for list with 1 element it does not work > >     *Main> :t headAny (Proxy @(Tail '[Bool])) $  insertAny 1 $ insertAny True [] >     headAny (Proxy @(Tail '[Bool])) $  insertAny 1 $ insertAny True [] >       :: Maybe * >     *Main> headAny (Proxy @(Tail '[Bool])) $  insertAny 1 $ insertAny True [] > >     :246:1: error: >         • No instance for (Show *) arising from a use of ‘print’ >         • In a stmt of an interactive GHCi command: print it > > ..... > > And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) > instance. I think, i've fixed everything. Eventually, it was very simple. > {-# LANGUAGE DataKinds #-} > {-# LANGUAGE RankNTypes #-} > {-# LANGUAGE KindSignatures #-} > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE TypeOperators #-} > {-# LANGUAGE PolyKinds #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE GADTs #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE FlexibleInstances #-} > {-# LANGUAGE MultiParamTypeClasses #-} > > import Data.Kind > import Data.Proxy > import Unsafe.Coerce > > class FromTypeMaybe2 k t where > fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t > > instance FromTypeMaybe2 'Nothing t where > fromTypeMaybe2 f _ _ = Nothing > > instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where > fromTypeMaybe2 f _ x = Just (f x) > > headAny2 > :: forall t ts > . FromTypeMaybe2 (MaybeHead ts) t > => Proxy ts -> [AnyData] -> Maybe t > headAny2 _ [] = Nothing > headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x > > type MaybeHead :: [t] -> Maybe t > type family MaybeHead ts where > MaybeHead '[] = 'Nothing > MaybeHead (x ': xs) = 'Just x > > type Tail:: [t] -> [t] > type family Tail ts where > Tail '[] = '[] > Tail (x ': xs) = xs > > data AnyData where > AnyData :: a -> AnyData > > unAny :: AnyData -> t > unAny (AnyData x) = unsafeCoerce x And now everything works: *Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] Just 1 and *Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] Nothing The only question, that remains is why defining 'Nothing resulting type to be 'GHC.Types.Any' in previous implementation instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any does not fix it? From benjamin.redelings at gmail.com Wed Jan 19 19:19:40 2022 From: benjamin.redelings at gmail.com (Benjamin Redelings) Date: Wed, 19 Jan 2022 11:19:40 -0800 Subject: [Haskell-cafe] Question about ambiguity and defaulting in recursive bindings Message-ID: <1ee2fd58-6946-dcce-74f5-4cc2fd5b9590@gmail.com> Hi, I am trying to understand how GHC treats the following declaration. f c i = if i == 10 then c else g c 'b' g 'a' w = f 'b' 10 g z w = z l = (f 'a' (1::Int), f 'a' (1.0::Double)) It seems to me like, after defaulting, f should have the following type:     Char -> Int -> Char However, looking at -ddump-tc, GHC is deriving the polymorphic type     forall a. (Eq a, Num a) => Char -> a -> Char That's much nicer, because its more flexible.  But I'm confused, because it looks like GHC is defaulting 'g', but not 'f', even though they are in the same recursive group.  This seems to contradict "Typing Haskell in Haskell", which is what I am looking at right now.  If that is correct, can anybody point me to a paper or documentation about how this works? More detail: 1. If I understand correctly, the definitions of `f` and `g` are mutually recursive, and should be typed together, and the declaration group is not restricted. 2. It seems like, before generalization, we have     f :: Char -> a -> Char     g :: Char -> Char -> Char     Predicates include (Eq a, Num a) 3. Looking at the paper "Typing Haskell in Haskell" (THIH), it looks like the predicates (Num a, Eq a) should cause an ambiguity in the definition of g: * a is present in the definition of f, but not the definition of g * so the type (Eq a, Num a) => Char -> Char -> Char is ambiguous. * more generally, it seems like THIH treats any predicates with a type variable that is part of some, but not all, types in the declaration group to be ambiguous.  Does this sound right? 4. Then, again following THIH, this ambiguous predicate should be defaulted to Int. I THINK this should lead to f :: Char -> Int -> Char g :: Char -> Char -> Char 5. However, I'm still not sure I'm understanding this right, because a few things still don't make sense: * First, THIH seems to eliminate the defaulted predicates without substituting a -> Int.  But the type for f DOES mention `a`, so how can we avoid substituting? * Second, GHC accepts the code with no warnings or errors. There is some kind of defaulting going on, because GHC rejects the code if I add "default ()". Is there some way for GHC to default only g, but not f? I wonder if this involves a difference between Haskell '98 and Haskell 2010? I also wonder how much I should rely on THIH?  Maybe the language has moved on since then? -BenRI -------------- next part -------------- An HTML attachment was scrubbed... URL: From benjamin.redelings at gmail.com Wed Jan 19 22:34:41 2022 From: benjamin.redelings at gmail.com (Benjamin Redelings) Date: Wed, 19 Jan 2022 14:34:41 -0800 Subject: [Haskell-cafe] Question about ambiguity and defaulting in recursive bindings In-Reply-To: <1ee2fd58-6946-dcce-74f5-4cc2fd5b9590@gmail.com> References: <1ee2fd58-6946-dcce-74f5-4cc2fd5b9590@gmail.com> Message-ID: 1. Hmm... Perhaps ghc changes the code to fgtuple:: (Eq a, Num a) => (Char -> a -> Char, Char -> Char -> Char) fgtuple dEq dNum = let f c i = if i == 10 then c else g c 'b' g 'a' w = f 'b' 10 g z w = z in (f,g) f :: forall a. (Eq a, Num) => Char -> a -> Char f dEq dNum = case fgtuple dEq dNum of (f,g) -> f g :: Char -> Char -> Char g = case fgtuple dEqInt dNumInt (f,g) -> g In order words, * the definition of fgtuple is not ambiguous. * the defaulting is applied only to the definition of g, not the definition of fgtuple. Does that sound right? 2. Running ghc -ddump-tc shows:   {Exports: [f <= f_a2gf                wrap: <>,              g <= g_a2gi                wrap: <> @ Integer $dEq_a2xJ $dNum_a2xK] The "wrap" code looks like the extra arguments that are applied by defaulting. -BenRI On 1/19/22 11:19 AM, Benjamin Redelings wrote: > Hi, > > I am trying to understand how GHC treats the following declaration. > > f c i = if i == 10 then c else g c 'b' > g 'a' w = f 'b' 10 > g z w = z > > l = (f 'a' (1::Int), f 'a' (1.0::Double)) > > It seems to me like, after defaulting, f should have the following type: > >     Char -> Int -> Char > > However, looking at -ddump-tc, GHC is deriving the polymorphic type > >     forall a. (Eq a, Num a) => Char -> a -> Char > > That's much nicer, because its more flexible.  But I'm confused, > because it looks like GHC is defaulting 'g', but not 'f', even though > they are in the same recursive group.  This seems to contradict > "Typing Haskell in Haskell", which is what I am looking at right now.  > If that is correct, can anybody point me to a paper or documentation > about how this works? > > More detail: > > 1. If I understand correctly, the definitions of `f` and `g` are > mutually recursive, and should be typed together, and the declaration > group is not restricted. > > 2. It seems like, before generalization, we have > >     f :: Char -> a -> Char >     g :: Char -> Char -> Char >     Predicates include (Eq a, Num a) > > 3. Looking at the paper "Typing Haskell in Haskell" (THIH), it looks > like the predicates (Num a, Eq a) should cause an ambiguity in the > definition of g: > > * a is present in the definition of f, but not the definition of g > > * so the type (Eq a, Num a) => Char -> Char -> Char is ambiguous. > > * more generally, it seems like THIH treats any predicates with a type > variable that is part of some, but not all, types in the declaration > group to be ambiguous.  Does this sound right? > > 4. Then, again following THIH, this ambiguous predicate should be > defaulted to Int. > > I THINK this should lead to > > f :: Char -> Int -> Char > g :: Char -> Char -> Char > > 5. However, I'm still not sure I'm understanding this right, because a > few things still don't make sense: > > * First, THIH seems to eliminate the defaulted predicates without > substituting a -> Int.  But the type for f DOES mention `a`, so how > can we avoid substituting? > > * Second, GHC accepts the code with no warnings or errors. There is > some kind of defaulting going on, because GHC rejects the code if I > add "default ()". Is there some way for GHC to default only g, but not f? > > I wonder if this involves a difference between Haskell '98 and Haskell > 2010? > > I also wonder how much I should rely on THIH?  Maybe the language has > moved on since then? > > -BenRI > -------------- next part -------------- An HTML attachment was scrubbed... URL: From sgf.dma at gmail.com Fri Jan 21 16:59:42 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Fri, 21 Jan 2022 19:59:42 +0300 Subject: [Haskell-cafe] Recursive constraints with type families Message-ID: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> Hi. I've stumbled upon a simple problem with recursive type family: > {-# LANGUAGE RankNTypes #-} > {-# LANGUAGE KindSignatures #-} > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE TypeOperators #-} > {-# LANGUAGE PolyKinds #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE UndecidableInstances #-} > > import GHC.TypeLits > import Data.Proxy > import Data.Kind > > type C :: Nat -> Constraint > type family C x where > C 0 = KnownNat 0 > --C x = (KnownNat x, C (x - 1)) > C x = (KnownNat x, C 0) > --C x = KnownNat x > > --type C2 x = (KnownNat x, C2 1) > > showNat :: forall (n :: Nat). C n => Proxy n -> String > showNat _ = show $ natVal (Proxy @n) and the error is Prelude> :r [1 of 1] Compiling Main ( constraint-type-family.lhs, interpreted ) constraint-type-family.lhs:31:22: error: • Could not deduce (KnownNat n) arising from a use of ‘natVal’ from the context: C n bound by the type signature for: showNat :: forall (n :: Nat). C n => Proxy n -> String at constraint-type-family.lhs:30:3-56 Possible fix: add (KnownNat n) to the context of the type signature for: showNat :: forall (n :: Nat). C n => Proxy n -> String • In the second argument of ‘($)’, namely ‘natVal (Proxy @n)’ In the expression: show $ natVal (Proxy @n) In an equation for ‘showNat’: showNat _ = show $ natVal (Proxy @n) | 31 | > showNat _ = show $ natVal (Proxy @n) | ^^^^^^^^^^^^^^^^^ If i write just C x = KnownNat x everything works fine. I guess, the reason is UndecidableInstances, but why and then, how can i build constraints recursively and make it work? Thanks. PS. Initially, this 'showNat' was something like countDown :: forall (n :: Nat). C n => Proxy n -> String countDown _ = let x = natVal (Proxy @n) in if x > 0 then show x ++ countDown (Proxy @(n - 1)) else "end" but it does not work. From godzbanebane at gmail.com Fri Jan 21 17:30:41 2022 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Fri, 21 Jan 2022 19:30:41 +0200 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> Message-ID: Hi! In order for you to reach any of the cases in C, the type family must be able to see if x is 0 or not. However, you're passing it an arbitrary n, so it has no way of knowing which case it should pick. GHC doesn't do any reasoning of the sort "well this constraint is available in all the cases of the type family, so I'll just add it". The solution here would be to separate your KnownNat constraint from whatever you want to calculate in your recursive type family: type C1 n = (KnownNat n, C n) type family C n ... countDown :: forall (n :: Nat). C1 n => Proxy n -> String countDown = ... Cheers, Georgi On Fri, Jan 21, 2022 at 7:00 PM Dmitriy Matrosov wrote: > Hi. > > I've stumbled upon a simple problem with recursive type family: > > > {-# LANGUAGE RankNTypes #-} > > {-# LANGUAGE KindSignatures #-} > > {-# LANGUAGE TypeApplications #-} > > {-# LANGUAGE TypeOperators #-} > > {-# LANGUAGE PolyKinds #-} > > {-# LANGUAGE TypeFamilies #-} > > {-# LANGUAGE StandaloneKindSignatures #-} > > {-# LANGUAGE ScopedTypeVariables #-} > > {-# LANGUAGE UndecidableInstances #-} > > > > import GHC.TypeLits > > import Data.Proxy > > import Data.Kind > > > > type C :: Nat -> Constraint > > type family C x where > > C 0 = KnownNat 0 > > --C x = (KnownNat x, C (x - 1)) > > C x = (KnownNat x, C 0) > > --C x = KnownNat x > > > > --type C2 x = (KnownNat x, C2 1) > > > > showNat :: forall (n :: Nat). C n => Proxy n -> String > > showNat _ = show $ natVal (Proxy @n) > > and the error is > > Prelude> :r > [1 of 1] Compiling Main ( constraint-type-family.lhs, > interpreted ) > > constraint-type-family.lhs:31:22: error: > • Could not deduce (KnownNat n) arising from a use of ‘natVal’ > from the context: C n > bound by the type signature for: > showNat :: forall (n :: Nat). C n => Proxy n -> > String > at constraint-type-family.lhs:30:3-56 > Possible fix: > add (KnownNat n) to the context of > the type signature for: > showNat :: forall (n :: Nat). C n => Proxy n -> String > • In the second argument of ‘($)’, namely ‘natVal (Proxy @n)’ > In the expression: show $ natVal (Proxy @n) > In an equation for ‘showNat’: showNat _ = show $ natVal (Proxy > @n) > | > 31 | > showNat _ = show $ natVal (Proxy @n) > | ^^^^^^^^^^^^^^^^^ > > If i write just > > C x = KnownNat x > > everything works fine. I guess, the reason is UndecidableInstances, but why > and then, how can i build constraints recursively and make it work? > > Thanks. > > PS. Initially, this 'showNat' was something like > > countDown :: forall (n :: Nat). C n => Proxy n -> String > countDown _ = let x = natVal (Proxy @n) > in if x > 0 > then show x ++ countDown (Proxy @(n - 1)) > else "end" > > but it does not work. > > _______________________________________________ > 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 sgf.dma at gmail.com Sat Jan 22 10:55:06 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Sat, 22 Jan 2022 13:55:06 +0300 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> Message-ID: <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> On 1/21/22 8:30 PM, Georgi Lyubenov wrote:> Hi! > > In order for you to reach any of the cases in C, the type family must be able to see if x is 0 or not. However, you're passing it an arbitrary n, so it has no way of knowing which case it should pick. > > GHC doesn't do any reasoning of the sort "well this constraint is available in all the cases of the type family, so I'll just add it". > > The solution here would be to separate your KnownNat constraint from whatever you want to calculate in your recursive type family: > > type C1 n = (KnownNat n, C n) > type family C n ... > > countDown :: forall (n :: Nat). C1 n => Proxy n -> String > countDown = ... Hi, Georgi. I see, thanks. But what i've tried to implement is type-level countdown: > {-# LANGUAGE RankNTypes #-} > {-# LANGUAGE KindSignatures #-} > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE TypeOperators #-} > {-# LANGUAGE DataKinds #-} > {-# LANGUAGE PolyKinds #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE ConstraintKinds #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE UndecidableInstances #-} > > import GHC.TypeLits > import Data.Proxy > import Data.Kind > import qualified Fcf as F > > type C :: Nat -> Constraint > type family C x where > C 0 = KnownNat 0 > C x = (KnownNat x, C (x - 1)) > > countDown :: forall (n :: Nat). C n => Proxy n -> String > countDown _ = let x = natVal (Proxy @n) > in if x > 0 > then show x ++ " " ++ countDown (Proxy @(n - 1)) > else "end" This code does not compile with *Main> :r [1 of 1] Compiling Main ( constraint-type-family-followup.lhs, interpreted ) constraint-type-family-followup.lhs:42:25: error: • Could not deduce (KnownNat n) arising from a use of ‘natVal’ from the context: C n bound by the type signature for: countDown :: forall (n :: Nat). C n => Proxy n -> String at constraint-type-family-followup.lhs:41:3-58 Possible fix: add (KnownNat n) to the context of the type signature for: countDown :: forall (n :: Nat). C n => Proxy n -> String • In the expression: natVal (Proxy @n) In an equation for ‘x’: x = natVal (Proxy @n) In the expression: let x = natVal (Proxy @n) in if x > 0 then show x ++ " " ++ countDown (Proxy @(n - 1)) else "end" | 42 | > countDown _ = let x = natVal (Proxy @n) | ^^^^^^^^^^^^^^^^^ constraint-type-family-followup.lhs:44:45: error: • Could not deduce: C (n - 1) arising from a use of ‘countDown’ from the context: C n bound by the type signature for: countDown :: forall (n :: Nat). C n => Proxy n -> String at constraint-type-family-followup.lhs:41:3-58 • In the second argument of ‘(++)’, namely ‘countDown (Proxy @(n - 1))’ In the second argument of ‘(++)’, namely ‘" " ++ countDown (Proxy @(n - 1))’ In the expression: show x ++ " " ++ countDown (Proxy @(n - 1)) • Relevant bindings include countDown :: Proxy n -> String (bound at constraint-type-family-followup.lhs:42:3) | 44 | > then show x ++ " " ++ countDown (Proxy @(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ If i try to get rid of cases in type family: > type C2 :: Nat -> Constraint > type family C2 x where > C2 x = F.If (F.Eval (x F.> 0)) > (KnownNat x, C2 (x - 1)) > (KnownNat 0) ghc eats all memory and hangs during type family calculation: *Main> :k! C2 3 ^CInterrupted. *Main> and using this as a constraint in 'countDown' results in: Prelude> :r [1 of 1] Compiling Main ( constraint-type-family-followup.lhs, interpreted ) constraint-type-family-followup.lhs:42:16: error: • Reduction stack overflow; size = 201 Though, adding the base case (and essentially making 'F.If' useless, but anyway) > type C2' :: Nat -> Constraint > type family C2' x where > C2' 0 = KnownNat 0 > C2' x = F.If (F.Eval (x F.> 0)) > (KnownNat x, C2' (x - 1)) > (KnownNat 0) fixes type calculation: *Main> :k! C2' 3 C2' 3 :: Constraint = (KnownNat 3, (KnownNat 2, (KnownNat 1, KnownNat 0))) but 'countDown' function does not compile with the same error as was with 'C'. May be someone can explain me, why it hangs? I'll be very grateful. And the other question, is how then should i implement such type-level count down function? Thanks. > Cheers, > > Georgi > > On Fri, Jan 21, 2022 at 7:00 PM Dmitriy Matrosov > wrote: > > Hi. > > I've stumbled upon a simple problem with recursive type family: > > > {-# LANGUAGE RankNTypes #-} > > {-# LANGUAGE KindSignatures #-} > > {-# LANGUAGE TypeApplications #-} > > {-# LANGUAGE TypeOperators #-} > > {-# LANGUAGE PolyKinds #-} > > {-# LANGUAGE TypeFamilies #-} > > {-# LANGUAGE StandaloneKindSignatures #-} > > {-# LANGUAGE ScopedTypeVariables #-} > > {-# LANGUAGE UndecidableInstances #-} > > > > import GHC.TypeLits > > import Data.Proxy > > import Data.Kind > > > > type C :: Nat -> Constraint > > type family C x where > >     C 0 = KnownNat 0 > >     --C x = (KnownNat x, C (x - 1)) > >     C x = (KnownNat x, C 0) > >     --C x = KnownNat x > > > > --type C2 x = (KnownNat x, C2 1) > > > > showNat :: forall (n :: Nat). C n => Proxy n -> String > > showNat _ = show $ natVal (Proxy @n) > > and the error is > >      Prelude> :r >      [1 of 1] Compiling Main             ( constraint-type-family.lhs, interpreted ) > >      constraint-type-family.lhs:31:22: error: >          • Could not deduce (KnownNat n) arising from a use of ‘natVal’ >            from the context: C n >              bound by the type signature for: >                         showNat :: forall (n :: Nat). C n => Proxy n -> String >              at constraint-type-family.lhs:30:3-56 >            Possible fix: >              add (KnownNat n) to the context of >                the type signature for: >                  showNat :: forall (n :: Nat). C n => Proxy n -> String >          • In the second argument of ‘($)’, namely ‘natVal (Proxy @n)’ >            In the expression: show $ natVal (Proxy @n) >            In an equation for ‘showNat’: showNat _ = show $ natVal (Proxy @n) >         | >      31 | > showNat _ = show $ natVal (Proxy @n) >         |                      ^^^^^^^^^^^^^^^^^ > > If i write just > >       C x = KnownNat x > > everything works fine. I guess, the reason is UndecidableInstances, but why > and then, how can i build constraints recursively and make it work? > > Thanks. > > PS. Initially, this 'showNat' was something like > >      countDown :: forall (n :: Nat). C n => Proxy n -> String >      countDown _ = let x = natVal (Proxy @n) >                    in  if x > 0 >                          then show x ++ countDown (Proxy @(n - 1)) >                          else "end" > > but it does not work. > > _______________________________________________ > 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 david.feuer at gmail.com Sun Jan 23 02:32:56 2022 From: david.feuer at gmail.com (David Feuer) Date: Sat, 22 Jan 2022 21:32:56 -0500 Subject: [Haskell-cafe] [ANN]: traverse-code Message-ID: I've put up a tiny little package[1], traverse-code, offering a generic way to "traverse" in Template Haskell's `Code m`. class TraverseCode t where traverseCode :: Quote m => (a -> Code m b) -> t a -> Code m (t b) I wrote this primarily as a way to "lift" operations on polymorphic data structures into Template Haskell. For example, for Data.Sequence, you can write triple :: a -> a -> a -> Seq a triple a b c = $$(sequenceCode $ fromList [ [||a||], [||b||], [||c||] ]) The `triple` function will not form its arguments into a list and then convert it to a sequence; rather, it will build the result sequence directly, using the underlying constructors. A generic default definition is available for all instances of Generics.Linear.Generic1. See linear-generics[2] for information about how to derive those. There's nothing particularly linear about traverse-code, but linear-generics has a more general Generic1 than GHC.Generics offers. [1] https://hackage.haskell.org/package/traverse-code [2] https://hackage.haskell.org/package/linear-generics From x at tomsmeding.com Sun Jan 23 08:55:53 2022 From: x at tomsmeding.com (Tom Smeding) Date: Sun, 23 Jan 2022 08:55:53 +0000 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> Message-ID: On Saturday, January 22nd, 2022 at 11:55 AM, Dmitriy Matrosov wrote: [...] > I see, thanks. But what i've tried to implement is type-level countdown: > > > {-# LANGUAGE RankNTypes #-} > > {-# LANGUAGE KindSignatures #-} > > {-# LANGUAGE TypeApplications #-} > > {-# LANGUAGE TypeOperators #-} > > {-# LANGUAGE DataKinds #-} > > {-# LANGUAGE PolyKinds #-} > > {-# LANGUAGE TypeFamilies #-} > > {-# LANGUAGE ConstraintKinds #-} > > {-# LANGUAGE StandaloneKindSignatures #-} > > {-# LANGUAGE ScopedTypeVariables #-} > > {-# LANGUAGE UndecidableInstances #-} > > > > import GHC.TypeLits > > import Data.Proxy > > import Data.Kind > > import qualified Fcf as F > > > > type C :: Nat -> Constraint > > type family C x where > > C 0 = KnownNat 0 > > C x = (KnownNat x, C (x - 1)) > > > > countDown :: forall (n :: Nat). C n => Proxy n -> String > > countDown _ = let x = natVal (Proxy @n) > > in if x > 0 > > then show x ++ " " ++ countDown (Proxy @(n - 1)) > > else "end" > > This code does not compile with > > *Main> :r > [1 of 1] Compiling Main ( constraint-type-family-followup.lhs, interpreted ) > > constraint-type-family-followup.lhs:42:25: error: > • Could not deduce (KnownNat n) arising from a use of ‘natVal’ > from the context: C n > bound by the type signature for: > countDown :: forall (n :: Nat). C n => Proxy n -> String > at constraint-type-family-followup.lhs:41:3-58 > Possible fix: > add (KnownNat n) to the context of > the type signature for: > countDown :: forall (n :: Nat). C n => Proxy n -> String > • In the expression: natVal (Proxy @n) > In an equation for ‘x’: x = natVal (Proxy @n) > In the expression: > let x = natVal (Proxy @n) > in > if x > 0 then > show x ++ " " ++ countDown (Proxy @(n - 1)) > else > "end" > | > 42 | > countDown _ = let x = natVal (Proxy @n) > | ^^^^^^^^^^^^^^^^^ > > constraint-type-family-followup.lhs:44:45: error: > • Could not deduce: C (n - 1) arising from a use of ‘countDown’ > from the context: C n > bound by the type signature for: > countDown :: forall (n :: Nat). C n => Proxy n -> String > at constraint-type-family-followup.lhs:41:3-58 > • In the second argument of ‘(++)’, namely > ‘countDown (Proxy @(n - 1))’ > In the second argument of ‘(++)’, namely > ‘" " ++ countDown (Proxy @(n - 1))’ > In the expression: show x ++ " " ++ countDown (Proxy @(n - 1)) > • Relevant bindings include > countDown :: Proxy n -> String > (bound at constraint-type-family-followup.lhs:42:3) > | > 44 | > then show x ++ " " ++ countDown (Proxy @(n - 1)) > | ^^^^^^^^^^^^^^^^^^^^^^^^^^ > > If i try to get rid of cases in type family: > > > type C2 :: Nat -> Constraint > > type family C2 x where > > C2 x = F.If (F.Eval (x F.> 0)) > > (KnownNat x, C2 (x - 1)) > > (KnownNat 0) > > ghc eats all memory and hangs during type family calculation: > > *Main> :k! C2 3 > ^CInterrupted. > *Main> [...] > May be someone can explain me, why it hangs? I'll be very grateful. Unfortunately I have no idea. Fcf looks wild, I have no idea what's going on there. > > And the other question, is how then should i implement such type-level count > down function? Using type classes: > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE DataKinds #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE UndecidableInstances #-} > > import GHC.TypeLits > import Data.Proxy > import Data.Kind > > type CountDown :: Nat -> Constraint > class CountDown n where > countDown :: Proxy n -> String > instance {-# OVERLAPPING #-} CountDown 0 where > countDown _ = "end" > instance {-# OVERLAPPABLE #-} (CountDown (n - 1), KnownNat n) => CountDown n where > countDown p = show (natVal p) ++ " " ++ countDown (Proxy @(n - 1)) Before I wrote this email I thought this would be possible using regular old type classes, but of course these instances are overlapping for the zero case. However, some pragmas make GHC do the right thing here. Cheers, Tom > > Thanks. > [...] > _______________________________________________ > 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 Sun Jan 23 21:05:13 2022 From: lysxia at gmail.com (Li-yao Xia) Date: Sun, 23 Jan 2022 16:05:13 -0500 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> Message-ID: <4ee0714d-dbc4-3e9b-1ac7-622a6215bbbb@gmail.com> Hi Dmitriy, On 2022-01-22 5:55 AM, Dmitriy Matrosov wrote: > > I see, thanks. But what i've tried to implement is type-level countdown: > [...] >> >> import GHC.TypeLits >> import Data.Proxy >> import Data.Kind >> import qualified Fcf as F >> >> type C :: Nat -> Constraint >> type family C x where >>     C 0 = KnownNat 0 >>     C x = (KnownNat x, C (x - 1)) >> >> countDown :: forall (n :: Nat). C n => Proxy n -> String >> countDown _ = let x = natVal (Proxy @n) >>               in  if x > 0 >>                     then show x ++ " " ++ countDown (Proxy @(n - 1)) >>                     else "end" > > This code does not compile The condition (x > 0) does not propagate any information at the type level. Such a thing is a feature of dependently typed languages, which Haskell is not. The compiler does not know that n > 0 in the first branch, so the constraint (C n) remains stuck. > If i try to get rid of cases in type family: > >> type C2 :: Nat -> Constraint >> type family C2 x where >>   C2 x = F.If (F.Eval (x F.> 0)) >>           (KnownNat x, C2 (x - 1)) >>           (KnownNat 0) > > ghc eats all memory and hangs during type family calculation: > >     *Main> :k! C2 3 >     ^CInterrupted. >     *Main> [...] > May be someone can explain me, why it hangs? I'll be very grateful. The rule of thumb here is that if a type family can be unfolded, it will be, regardless of context. Since there is only one clause, (C2 x) can always be unfolded, and then C2 (x-1) will be unfolded (regardless of whether the "If" condition is true or false) and then (C2 ((x-1)-1)), etc. There is a trick with first-class-families to control evaluation with the Eval type family, by making the branches reduce to uninterpreted symbols, rather than type family applications. Two key components of this trick: - C2 must be a first-class type family (an "uninterpreted symbol") - Eval must be applied outside of If data C2 :: Nat -> F.Exp Constraint type instance F.Eval (C2 x) = (KnownNat x, F.Eval (F.If (F.Eval (x F.> 0)) (C2 (x - 1)) (F.Pure (() :: Constraint)))) ghci: > :k! F.Eval (C2 3) F.Eval (C2 3) :: Constraint = (KnownNat 3, (KnownNat 2, (KnownNat 1, (KnownNat 0, () :: Constraint)))) > And the other question, is how then should i implement such type-level > count > down function? To make constraints sensitive to control-flow, you need at least GADTs. A general solution is provided by singletons, to simulate dependent types in Haskell. For small tasks though, it's often easier to make your own singletons. One version of countdown looks like this: countdown :: forall n. F.Eval (C2 n) => Proxy n -> String countdown _ = case getBool @(F.Eval (n F.> 0)) of STrue -> show (natVal @n Proxy) ++ " " ++ countdown @(n-1) Proxy SFalse -> "boom" Where the comparison (n > 0) is done at the type level and reflected by a boolean singleton value, of type SBool: data SBool (a :: Bool) where SFalse :: SBool 'False STrue :: SBool 'True Of course, the compiler doesn't know whether n is positive, so this information must be provided as a constraint (or derived somehow): -- Add IsBool constraint in C2, for every If condition data C2 :: Nat -> F.Exp Constraint type instance F.Eval (C2 x) = (KnownNat x, IsBool (F.Eval (x F.> 0)), F.Eval (F.If (F.Eval (x F.> 0)) (C2 (x - 1)) (F.Pure (() :: Constraint)))) The IsBool class turns a known type-level boolean into a boolean singleton value indexed by that same boolean: class IsBool b where getBool :: SBool b instance IsBool 'True where getBool = STrue instance IsBool 'False where getBool = SFalse Full gist: https://gist.github.com/Lysxia/cf47807bbbcbb572896b350d66162a25 Regards, Li-yao From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Jan 24 21:17:53 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 24 Jan 2022 21:17:53 +0000 Subject: [Haskell-cafe] Guards on variable bindings Message-ID: According to GHC there are multiple declarations of bar, but not of foo. I don't understand. Why is it not valid to have multiple clauses for a variable binding? Tom bar | False = () bar = () foo _ | False = () foo _ = () From allbery.b at gmail.com Mon Jan 24 21:24:43 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 24 Jan 2022 16:24:43 -0500 Subject: [Haskell-cafe] Guards on variable bindings In-Reply-To: References: Message-ID: I think because it desugars to a case-of and there's nothing to case on in the first one? On Mon, Jan 24, 2022 at 4:18 PM Tom Ellis wrote: > > According to GHC there are multiple declarations of bar, but not of > foo. I don't understand. Why is it not valid to have multiple > clauses for a variable binding? > > > Tom > > > bar | False = () > bar = () > > foo _ | False = () > foo _ = () > _______________________________________________ > 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. -- brandon s allbery kf8nh allbery.b at gmail.com From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Jan 24 21:28:32 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 24 Jan 2022 21:28:32 +0000 Subject: [Haskell-cafe] Guards on variable bindings In-Reply-To: References: Message-ID: I don't think that can be the reason. It is possible to have a single clause with multiple guards: bar | False = () | True = () It's just not possible to have multiple clauses if one of them is guarded, apparently. On Mon, Jan 24, 2022 at 04:24:43PM -0500, Brandon Allbery wrote: > I think because it desugars to a case-of and there's nothing to case > on in the first one? > > On Mon, Jan 24, 2022 at 4:18 PM Tom Ellis > wrote: > > > > According to GHC there are multiple declarations of bar, but not of > > foo. I don't understand. Why is it not valid to have multiple > > clauses for a variable binding? > > > > > > Tom > > > > > > bar | False = () > > bar = () > > > > foo _ | False = () > > foo _ = () From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Jan 24 21:32:16 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 24 Jan 2022 21:32:16 +0000 Subject: [Haskell-cafe] Guards on variable bindings In-Reply-To: References: Message-ID: On Mon, Jan 24, 2022 at 09:28:32PM +0000, Tom Ellis wrote: > I don't think that can be the reason. It is possible to have a single > clause with multiple guards: > > bar | False = () > | True = () > > It's just not possible to have multiple clauses if one of them is > guarded, apparently. Or rather "even if one of them is guarded". It's a bit more understandable to forbid multiple clauses if the first one isn't guarded. From allbery.b at gmail.com Mon Jan 24 21:33:17 2022 From: allbery.b at gmail.com (Brandon Allbery) Date: Mon, 24 Jan 2022 16:33:17 -0500 Subject: [Haskell-cafe] Guards on variable bindings In-Reply-To: References: Message-ID: That seems fine to me because they can be combined into a single case-of. I just don't see how you'd do so with an unguarded clause; guess I'd have to look at -ddump-ds to see what exactly it's doing with them, On Mon, Jan 24, 2022 at 4:29 PM Tom Ellis wrote: > > I don't think that can be the reason. It is possible to have a single > clause with multiple guards: > > bar | False = () > | True = () > > It's just not possible to have multiple clauses if one of them is > guarded, apparently. > > > On Mon, Jan 24, 2022 at 04:24:43PM -0500, Brandon Allbery wrote: > > I think because it desugars to a case-of and there's nothing to case > > on in the first one? > > > > On Mon, Jan 24, 2022 at 4:18 PM Tom Ellis > > wrote: > > > > > > According to GHC there are multiple declarations of bar, but not of > > > foo. I don't understand. Why is it not valid to have multiple > > > clauses for a variable binding? > > > > > > > > > Tom > > > > > > > > > bar | False = () > > > bar = () > > > > > > foo _ | False = () > > > foo _ = () > _______________________________________________ > 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. -- brandon s allbery kf8nh allbery.b at gmail.com From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Tue Jan 25 14:16:30 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Tue, 25 Jan 2022 14:16:30 +0000 Subject: [Haskell-cafe] Missing feature of Coercible, or necessary caution? Message-ID: Consider the following program. {-# LANGUAGE TypeApplications #-} import Data.IntMap (IntMap, mapKeysMonotonic, Key) import Data.Coerce (coerce) newtype MyMap = MyMap (IntMap Bool) doesn'tWork :: (Key -> Key) -> MyMap -> MyMap doesn'tWork = coerce mapKeysMonotonic works :: (Key -> Key) -> MyMap -> MyMap works = coerce (mapKeysMonotonic @Bool) mapKeysmonotonic has type (Key -> Key) -> IntMap a -> IntMap a and we attempt to coerce it to type (Key -> Key) -> MyMap -> MyMap since MyMap is a newtype around IntMap Bool this ends up generating the constraint Coercible a Bool and there is no way to specify that constraint given that a doesn't otherwise appear in the top-level type. Hence doesn'tWork will not type check. If I force the type of a to be Bool using a TypeApplication then it does type check (works). But is this a missing feature of GHC's Coercible system? Since a is not otherwise constrained is it not valid for GHC to choose it to be Bool ? Coercible instances contain now observable content so no observable behaviour could depend on the particular choice of Coercible a Bool instance, and choosing a ~ Bool is the natural one. Is there some violation of type safety or otherwise broken behaviour that could arise from choosing arbitrary Coercible instances on type variables that are not otherwise constrained? Tom From lists at richarde.dev Tue Jan 25 16:56:14 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Tue, 25 Jan 2022 16:56:14 +0000 Subject: [Haskell-cafe] Missing feature of Coercible, or necessary caution? In-Reply-To: References: Message-ID: <010f017e922aa181-ed4d93f5-cec3-4713-9847-c71362349da0-000000@us-east-2.amazonses.com> Good point. The constraint `Coercible a Bool` will not default `a` to Bool, because `a` could have other valid instantiations, such as `Identity Bool`. But you observe that, if there are no other constraints on `a`, then the choice of `a` does not matter, and so we might as well choose `a := Bool`. This is actually much like the fact that GHC accepts `length []`, even though it does not know what the element type of the list is. I think this can rightly be classed as a bug in GHC. If you submit a bug report, perhaps I will enjoy implementing a fix. :) Thanks, Richard > On Jan 25, 2022, at 9:16 AM, Tom Ellis wrote: > > Consider the following program. > > {-# LANGUAGE TypeApplications #-} > > import Data.IntMap (IntMap, mapKeysMonotonic, Key) > import Data.Coerce (coerce) > > newtype MyMap = MyMap (IntMap Bool) > > doesn'tWork :: (Key -> Key) -> MyMap -> MyMap > doesn'tWork = coerce mapKeysMonotonic > > works :: (Key -> Key) -> MyMap -> MyMap > works = coerce (mapKeysMonotonic @Bool) > > mapKeysmonotonic has type > > (Key -> Key) -> IntMap a -> IntMap a > > and we attempt to coerce it to type > > (Key -> Key) -> MyMap -> MyMap > > since MyMap is a newtype around IntMap Bool this ends up > generating the constraint > > Coercible a Bool > > and there is no way to specify that constraint given that a doesn't > otherwise appear in the top-level type. Hence doesn'tWork will not > type check. If I force the type of a to be Bool using a > TypeApplication then it does type check (works). > > But is this a missing feature of GHC's Coercible system? Since a is > not otherwise constrained is it not valid for GHC to choose it to be > Bool ? Coercible instances contain now observable content so no > observable behaviour could depend on the particular choice of Coercible a Bool > instance, and choosing a ~ Bool is the natural one. > > Is there some violation of type safety or otherwise broken behaviour > that could arise from choosing arbitrary Coercible instances on type > variables that are not otherwise constrained? > > Tom > _______________________________________________ > 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 tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Tue Jan 25 17:21:11 2022 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Tue, 25 Jan 2022 17:21:11 +0000 Subject: [Haskell-cafe] Missing feature of Coercible, or necessary caution? In-Reply-To: <010f017e922aa181-ed4d93f5-cec3-4713-9847-c71362349da0-000000@us-east-2.amazonses.com> References: <010f017e922aa181-ed4d93f5-cec3-4713-9847-c71362349da0-000000@us-east-2.amazonses.com> Message-ID: Bug report submitted and assigned to you :) https://gitlab.haskell.org/ghc/ghc/-/issues/21003 On Tue, Jan 25, 2022 at 04:56:14PM +0000, Richard Eisenberg wrote: > Good point. The constraint `Coercible a Bool` will not default `a` > to Bool, because `a` could have other valid instantiations, such as > `Identity Bool`. But you observe that, if there are no other > constraints on `a`, then the choice of `a` does not matter, and so > we might as well choose `a := Bool`. This is actually much like the > fact that GHC accepts `length []`, even though it does not know what > the element type of the list is. > > I think this can rightly be classed as a bug in GHC. If you submit a > bug report, perhaps I will enjoy implementing a fix. :) > > > On Jan 25, 2022, at 9:16 AM, Tom Ellis wrote: > > > > Consider the following program. > > > > {-# LANGUAGE TypeApplications #-} > > > > import Data.IntMap (IntMap, mapKeysMonotonic, Key) > > import Data.Coerce (coerce) > > > > newtype MyMap = MyMap (IntMap Bool) > > > > doesn'tWork :: (Key -> Key) -> MyMap -> MyMap > > doesn'tWork = coerce mapKeysMonotonic > > > > works :: (Key -> Key) -> MyMap -> MyMap > > works = coerce (mapKeysMonotonic @Bool) > > > > mapKeysmonotonic has type > > > > (Key -> Key) -> IntMap a -> IntMap a > > > > and we attempt to coerce it to type > > > > (Key -> Key) -> MyMap -> MyMap > > > > since MyMap is a newtype around IntMap Bool this ends up > > generating the constraint > > > > Coercible a Bool > > > > and there is no way to specify that constraint given that a doesn't > > otherwise appear in the top-level type. Hence doesn'tWork will not > > type check. If I force the type of a to be Bool using a > > TypeApplication then it does type check (works). > > > > But is this a missing feature of GHC's Coercible system? Since a is > > not otherwise constrained is it not valid for GHC to choose it to be > > Bool ? Coercible instances contain now observable content so no > > observable behaviour could depend on the particular choice of Coercible a Bool > > instance, and choosing a ~ Bool is the natural one. > > > > Is there some violation of type safety or otherwise broken behaviour > > that could arise from choosing arbitrary Coercible instances on type > > variables that are not otherwise constrained? From sgf.dma at gmail.com Wed Jan 26 14:51:28 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Wed, 26 Jan 2022 17:51:28 +0300 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: <4ee0714d-dbc4-3e9b-1ac7-622a6215bbbb@gmail.com> References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> <4ee0714d-dbc4-3e9b-1ac7-622a6215bbbb@gmail.com> Message-ID: <5b4cb913-70ae-d90d-09f8-b0baf8baf495@gmail.com> Hi Li-yao. Thank you for detailed answer! It was really helpful, but i have a few more questions. On 1/24/22 12:05 AM, Li-yao Xia wrote: > On 2022-01-22 5:55 AM, Dmitriy Matrosov wrote: >> >> If i try to get rid of cases in type family: >> >>> type C2 :: Nat -> Constraint >>> type family C2 x where >>> C2 x = F.If (F.Eval (x F.> 0)) >>> (KnownNat x, C2 (x - 1)) >>> (KnownNat 0) >> >> ghc eats all memory and hangs during type family calculation: > > [...] > > The rule of thumb here is that if a type family can be unfolded, it will > be, regardless of context. Since there is only one clause, (C2 x) can > always be unfolded, and then C2 (x-1) will be unfolded (regardless of > whether the "If" condition is true or false) and then (C2 ((x-1)-1)), etc. > > There is a trick with first-class-families to control evaluation with the > Eval type family, by making the branches reduce to uninterpreted symbols, > rather than type family applications. > > Two key components of this trick: > > - C2 must be a first-class type family (an "uninterpreted symbol") > - Eval must be applied outside of If So, the key of this trick is to make impossible to unfold type family without evaluating 'If' ? I mean, since type C :: Nat -> Constraint type family C x where C 0 = KnownNat 0 C x = (KnownNat x, C (x - 1)) terminates, but type instance F.Eval (C2' x) = (KnownNat x, --( F.If (F.Eval (x F.> 0)) ( F.If 'False (F.Eval (C2' (x - 1))) (() :: Constraint) ) ) hangs forever (even (F.If 'False) above makes no difference), i suppose, that just having many type family instances (like Eval has) does not force ghc to evaluate (x - 1) and If condition. I need something like type instance F.Eval (C2' 0) = (() :: Constraint) type instance F.Eval (C2' x) = (KnownNat x, F.Eval (C2' (x - 1))) which does not compile. Thus, i need If to be an argument for Eval (like in your code below), so ghc is forced to evaluate it to unfold type family further. Does this sound correct? > > data C2 :: Nat -> F.Exp Constraint > type instance F.Eval (C2 x) = > (KnownNat x, > F.Eval (F.If (F.Eval (x F.> 0)) > (C2 (x - 1)) > (F.Pure (() :: Constraint)))) > > ghci: > > :k! F.Eval (C2 3) > F.Eval (C2 3) :: Constraint > = (KnownNat 3, > (KnownNat 2, (KnownNat 1, (KnownNat 0, () :: Constraint)))) > > >> And the other question, is how then should i implement such type-level count >> down function? > > To make constraints sensitive to control-flow, you need at least GADTs. A > general solution is provided by singletons, to simulate dependent types in > Haskell. For small tasks though, it's often easier to make your own > singletons. > > One version of countdown looks like this: > > > countdown :: forall n. F.Eval (C2 n) => Proxy n -> String > countdown _ = > case getBool @(F.Eval (n F.> 0)) of > STrue -> show (natVal @n Proxy) ++ " " ++ countdown @(n-1) Proxy > SFalse -> "boom" So, i can't use plain Bool with something like class IsBool b where getBool :: Proxy b -> Bool because in that case both True and False branches of case would have the same type and ghc can't figure out by looking at plain Bool whether type level condition (n F.> 0) was true or false, right? Also, i've tried to make a slightly different conditions in type family and in getBool application. E.g. if i use getBool3 @(F.Eval ((n + 1) F.> 1)) then in type family only ((n + 1) F.> 1) or ((n + 1) F.> (0 + 1)) variants will work, but with smth like (n F.> 0) ghc won't be able to resolve constraints. So, does ghc take condition from getBool application literally and then uses its result to evaluates If in type family? Thanks. From lysxia at gmail.com Wed Jan 26 15:14:35 2022 From: lysxia at gmail.com (Li-yao Xia) Date: Wed, 26 Jan 2022 10:14:35 -0500 Subject: [Haskell-cafe] Recursive constraints with type families In-Reply-To: <5b4cb913-70ae-d90d-09f8-b0baf8baf495@gmail.com> References: <0e9f4782-dbba-fb10-4d1b-fb6b36584a9a@gmail.com> <87895d0e-39fc-566c-0e0f-e0876e764ee8@gmail.com> <4ee0714d-dbc4-3e9b-1ac7-622a6215bbbb@gmail.com> <5b4cb913-70ae-d90d-09f8-b0baf8baf495@gmail.com> Message-ID: <47e4372f-118c-667c-a785-275fc2fe0d04@gmail.com> On 2022-01-26 9:51 AM, Dmitriy Matrosov wrote: > So, the key of this trick is to make impossible to unfold type family > without > evaluating 'If' ? > Yes! > I need something like > >     type instance F.Eval (C2' 0) = (() :: Constraint) >     type instance F.Eval (C2' x) = (KnownNat x, F.Eval (C2' (x - 1))) > > which does not compile. Thus, i need If to be an argument for Eval (like in > your code below), so ghc is forced to evaluate it to unfold type family > further. Does this sound correct? That sounds correct. Another problem with closed type families here is that there is no construct for "x is not 0" that would let you know to take the branch "C x = (KnownNat x, C (x-1))". The general workaround used here is to turn the comparison to a boolean and then reify that boolean. At that point, you don't have to use `If`, you can also declare a new type family to match on that boolean, but it gets tedious for the same reason we use "if" at the term level rather than defining a new function for every conditional. > So, i can't use plain Bool with something like > >     class IsBool b where >         getBool :: Proxy b -> Bool > > because in that case both True and False branches of case would have the > same > type and ghc can't figure out by looking at plain Bool whether type level > condition (n F.> 0) was true or false, right? > Indeed. > So, does ghc take condition from getBool application > literally > and then uses its result to evaluates If in type family? That's right, GHC just takes the condition literally, it has no understanding of the meaning of `>` and `+` to draw logical inferences about them. Nevertheless, you might be interested in ghc-typelits-natnormalize, a plugin which equips GHC with a few such reasoning capabilities. Or Liquid Haskell, for an even more powerful approach. https://hackage.haskell.org/package/ghc-typelits-natnormalise https://ucsd-progsys.github.io/liquidhaskell/ From lists at richarde.dev Wed Jan 26 16:56:22 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Wed, 26 Jan 2022 16:56:22 +0000 Subject: [Haskell-cafe] Question about ambiguity and defaulting in recursive bindings In-Reply-To: References: <1ee2fd58-6946-dcce-74f5-4cc2fd5b9590@gmail.com> Message-ID: <010f017e97511bbe-54585684-0c8f-497b-868f-e1f26cc958da-000000@us-east-2.amazonses.com> Yes, indeed. That is precisely what GHC does! Well done discovering this. :) Richard > On Jan 19, 2022, at 5:34 PM, Benjamin Redelings wrote: > > 1. Hmm... Perhaps ghc changes the code to > > fgtuple:: (Eq a, Num a) => (Char -> a -> Char, Char -> Char -> Char) > fgtuple dEq dNum = > let f c i = if i == 10 then c else g c 'b' > g 'a' w = f 'b' 10 > g z w = z > in (f,g) > > f :: forall a. (Eq a, Num) => Char -> a -> Char > f dEq dNum = case fgtuple dEq dNum of (f,g) -> f > > g :: Char -> Char -> Char > g = case fgtuple dEqInt dNumInt (f,g) -> g > In order words, > > * the definition of fgtuple is not ambiguous. > > * the defaulting is applied only to the definition of g, not the definition of fgtuple. > > Does that sound right? > > 2. Running ghc -ddump-tc shows: > > {Exports: [f <= f_a2gf > wrap: <>, > g <= g_a2gi > wrap: <> @ Integer $dEq_a2xJ $dNum_a2xK] > The "wrap" code looks like the extra arguments that are applied by defaulting. > > -BenRI > > On 1/19/22 11:19 AM, Benjamin Redelings wrote: > >> Hi, >> >> I am trying to understand how GHC treats the following declaration. >> >> f c i = if i == 10 then c else g c 'b' >> g 'a' w = f 'b' 10 >> g z w = z >> >> l = (f 'a' (1::Int), f 'a' (1.0::Double)) >> It seems to me like, after defaulting, f should have the following type: >> >> Char -> Int -> Char >> However, looking at -ddump-tc, GHC is deriving the polymorphic type >> >> forall a. (Eq a, Num a) => Char -> a -> Char >> That's much nicer, because its more flexible. But I'm confused, because it looks like GHC is defaulting 'g', but not 'f', even though they are in the same recursive group. This seems to contradict "Typing Haskell in Haskell", which is what I am looking at right now. If that is correct, can anybody point me to a paper or documentation about how this works? >> >> More detail: >> >> 1. If I understand correctly, the definitions of `f` and `g` are mutually recursive, and should be typed together, and the declaration group is not restricted. >> >> 2. It seems like, before generalization, we have >> >> f :: Char -> a -> Char >> g :: Char -> Char -> Char >> Predicates include (Eq a, Num a) >> 3. Looking at the paper "Typing Haskell in Haskell" (THIH), it looks like the predicates (Num a, Eq a) should cause an ambiguity in the definition of g: >> >> * a is present in the definition of f, but not the definition of g >> >> * so the type (Eq a, Num a) => Char -> Char -> Char is ambiguous. >> >> * more generally, it seems like THIH treats any predicates with a type variable that is part of some, but not all, types in the declaration group to be ambiguous. Does this sound right? >> >> 4. Then, again following THIH, this ambiguous predicate should be defaulted to Int. >> >> I THINK this should lead to >> >> f :: Char -> Int -> Char >> g :: Char -> Char -> Char >> 5. However, I'm still not sure I'm understanding this right, because a few things still don't make sense: >> >> * First, THIH seems to eliminate the defaulted predicates without substituting a -> Int. But the type for f DOES mention `a`, so how can we avoid substituting? >> >> * Second, GHC accepts the code with no warnings or errors. There is some kind of defaulting going on, because GHC rejects the code if I add "default ()". Is there some way for GHC to default only g, but not f? >> >> I wonder if this involves a difference between Haskell '98 and Haskell 2010? >> >> I also wonder how much I should rely on THIH? Maybe the language has moved on since then? >> >> -BenRI >> > _______________________________________________ > 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 lists at richarde.dev Wed Jan 26 19:38:46 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Wed, 26 Jan 2022 19:38:46 +0000 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> Message-ID: <010f017e97e5c988-9f08b030-a003-46ec-a0c0-50788fbd5c5c-000000@us-east-2.amazonses.com> I was at a conference last week and didn't have time to respond... but now that I return to this, I still don't really understand what your question is. Sorry! I think this will help: Why invoke GHC.Types.Any at all? What are you hoping to accomplish with GHC.Types.Any? Thanks, Richard > On Jan 18, 2022, at 8:10 AM, Dmitriy Matrosov wrote: > > > > On 1/17/22 6:49 PM, Dmitriy Matrosov wrote: >>> {-# LANGUAGE DataKinds #-} >>> {-# LANGUAGE RankNTypes #-} >>> {-# LANGUAGE KindSignatures #-} >>> {-# LANGUAGE TypeApplications #-} >>> {-# LANGUAGE TypeOperators #-} >>> {-# LANGUAGE PolyKinds #-} >>> {-# LANGUAGE TypeFamilies #-} >>> {-# LANGUAGE GADTs #-} >>> {-# LANGUAGE StandaloneKindSignatures #-} >>> {-# LANGUAGE ScopedTypeVariables #-} >>> {-# LANGUAGE FlexibleContexts #-} >>> >>> import Data.Kind >>> import Data.Proxy >>> import Unsafe.Coerce >>> import qualified GHC.Types as GHC.Types >>> >>> class FromTypeMaybe k where >>> type ToType k >>> fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) >>> instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where >>> --type ToType 'Nothing = GHC.Types.Any >>> type ToType 'Nothing = t >>> fromTypeMaybe f _ x = Nothing >>> instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where >>> type ToType ('Just t) = t >>> fromTypeMaybe f _ x = Just (f x) >> then i've written a little more: >>> type MaybeHead :: [t] -> Maybe t >>> type family MaybeHead ts where >>> MaybeHead '[] = 'Nothing >>> MaybeHead (x ': xs) = 'Just x >>> >>> type Tail:: [t] -> [t] >>> type family Tail ts where >>> Tail '[] = '[] >>> Tail (x ': xs) = xs >>> >>> data AnyData where >>> AnyData :: a -> AnyData >>> >>> unAny :: AnyData -> t >>> unAny (AnyData x) = unsafeCoerce x >>> >>> insertAny :: t -> [AnyData] -> [AnyData] >>> insertAny x zs = AnyData x : zs >>> >>> headAny >>> :: forall ts >>> . FromTypeMaybe (MaybeHead ts) >>> => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) >>> headAny _ [] = Nothing >>> headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x >> And now it works, when type-level list is explicitly specified, like: >> *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] >> Nothing >> *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] >> Just 1 >> *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] >> Just 1 >> but if i use 'Tail' type-function first, it works only in two cases: >> for list with 2 or more elements >> *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >> :: Maybe Int >> *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >> Just 1 >> and empty list >> *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >> :: Maybe t >> *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >> Nothing >> But for list with 1 element it does not work >> *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >> :: Maybe * >> *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >> :246:1: error: >> • No instance for (Show *) arising from a use of ‘print’ >> • In a stmt of an interactive GHCi command: print it >> ..... >> And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) >> instance. > > I think, i've fixed everything. Eventually, it was very simple. > >> {-# LANGUAGE DataKinds #-} >> {-# LANGUAGE RankNTypes #-} >> {-# LANGUAGE KindSignatures #-} >> {-# LANGUAGE TypeApplications #-} >> {-# LANGUAGE TypeOperators #-} >> {-# LANGUAGE PolyKinds #-} >> {-# LANGUAGE TypeFamilies #-} >> {-# LANGUAGE GADTs #-} >> {-# LANGUAGE StandaloneKindSignatures #-} >> {-# LANGUAGE ScopedTypeVariables #-} >> {-# LANGUAGE FlexibleInstances #-} >> {-# LANGUAGE MultiParamTypeClasses #-} >> >> import Data.Kind >> import Data.Proxy >> import Unsafe.Coerce >> >> class FromTypeMaybe2 k t where >> fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t >> >> instance FromTypeMaybe2 'Nothing t where >> fromTypeMaybe2 f _ _ = Nothing >> >> instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where >> fromTypeMaybe2 f _ x = Just (f x) >> >> headAny2 >> :: forall t ts >> . FromTypeMaybe2 (MaybeHead ts) t >> => Proxy ts -> [AnyData] -> Maybe t >> headAny2 _ [] = Nothing >> headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x >> >> type MaybeHead :: [t] -> Maybe t >> type family MaybeHead ts where >> MaybeHead '[] = 'Nothing >> MaybeHead (x ': xs) = 'Just x >> >> type Tail:: [t] -> [t] >> type family Tail ts where >> Tail '[] = '[] >> Tail (x ': xs) = xs >> >> data AnyData where >> AnyData :: a -> AnyData >> >> unAny :: AnyData -> t >> unAny (AnyData x) = unsafeCoerce x > > And now everything works: > > *Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] > Nothing > *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] > Just 1 > *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] > Just 1 > > and > > *Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] > Just 1 > *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] > Nothing > *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] > Nothing > > The only question, that remains is why defining 'Nothing resulting type to be > 'GHC.Types.Any' in previous implementation > > instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where > type ToType 'Nothing = GHC.Types.Any > > does not fix it? > _______________________________________________ > 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 sgf.dma at gmail.com Thu Jan 27 15:25:52 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Thu, 27 Jan 2022 18:25:52 +0300 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: <010f017e97e5c988-9f08b030-a003-46ec-a0c0-50788fbd5c5c-000000@us-east-2.amazonses.com> References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> <010f017e97e5c988-9f08b030-a003-46ec-a0c0-50788fbd5c5c-000000@us-east-2.amazonses.com> Message-ID: <6d48ca81-edef-9cac-0417-65c6c2713eb7@gmail.com> On 1/26/22 10:38 PM, Richard Eisenberg wrote: > I was at a conference last week and didn't have time to respond... but now that I return to this, I still don't really understand what your question is. Sorry! > > I think this will help: Why invoke GHC.Types.Any at all? What are you hoping to accomplish with GHC.Types.Any? Well, that's more of a theoretical question. As i wrote earlier, i've fixed this example (by using type-class definition similar to IsLabel and without GHC.Types.Any). But anyway, i try to explain shorter. I've had the following code, which defines head function for using on list of existentials and coercing the head back to original type according to type-level list: > {-# LANGUAGE DataKinds #-} > {-# LANGUAGE RankNTypes #-} > {-# LANGUAGE KindSignatures #-} > {-# LANGUAGE TypeApplications #-} > {-# LANGUAGE TypeOperators #-} > {-# LANGUAGE PolyKinds #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE GADTs #-} > {-# LANGUAGE StandaloneKindSignatures #-} > {-# LANGUAGE ScopedTypeVariables #-} > {-# LANGUAGE FlexibleContexts #-} > > import Data.Kind > import Data.Proxy > import Unsafe.Coerce > import qualified GHC.Types as GHC.Types > > class FromTypeMaybe k where > type ToType k > fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) > instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where > --type ToType 'Nothing = GHC.Types.Any > type ToType 'Nothing = t > fromTypeMaybe f _ x = Nothing > instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where > type ToType ('Just t) = t > fromTypeMaybe f _ x = Just (f x) > > type MaybeHead :: [t] -> Maybe t > type family MaybeHead ts where > MaybeHead '[] = 'Nothing > MaybeHead (x ': xs) = 'Just x > > type Tail :: [t] -> [t] > type family Tail ts where > Tail '[] = '[] > Tail (x ': xs) = xs > > data AnyData where > AnyData :: a -> AnyData > > unAny :: AnyData -> t > unAny (AnyData x) = unsafeCoerce x > > headAny > :: forall ts > . FromTypeMaybe (MaybeHead ts) > => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) > headAny _ [] = Nothing > headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x This code works, when type-level list specified explicitly, like *Main> headAny @('[Int, Bool]) Proxy [AnyData 1, AnyData True] Just 1 but when i use 'Tail' function on type-level list with 1 element, it does not work: *Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] :22:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it Though on list with many elements and with empty list everything works: *Main> headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] Nothing When i've tried to understand why, i've noticed some similarities between working empty list case and non-working 1-element case: both these cases work through 'Nothing instance of 'FromTypeMaybe' type class, but type variable t is defined differently: *Main> :k! MaybeHead (Tail '[]) MaybeHead (Tail '[]) :: Maybe t = 'Nothing *Main> :k! MaybeHead (Tail '[Bool]) MaybeHead (Tail '[Bool]) :: Maybe * = 'Nothing So, with empty list type variable t remains unbound, but with 1-element list it is bound to Type. And then (ToType 'Nothing) is defined accordingly: *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = * And, no surprise, that there's no (Show Type) instance: *Main> show $ headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] :38:1: error: • No instance for (Show *) arising from a use of ‘show’ Until that moment, i understand everything (i think). But then ghc somehow manages to find Show instance for GHC.Types.Any (or may be not, but how does it print result for empty list then?): *Main> show $ headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] "Nothing" And that's the first thing i don't understand: there's should be no Show instance, but still.. Then i thought, that by defining (ToType 'Nothing) to be GHC.Types.Any instead of t: instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any fromTypeMaybe f _ x = Nothing i may fix 1-element case. Type evaluation looked promising: *Main> :k! (MaybeHead (Tail '[])) (MaybeHead (Tail '[])) :: Maybe t = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any but it does not work: *Main> show $ headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] :44:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘show’ *Main> show $ headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] :45:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘show’ And that's the second thing i don't understand: why it does not work, when i explicitly define type to be equal to GHC.Types.Any? Thanks. PS. I've read "Any types" notes in GHC.Builtin.Types, but apart from that ghc uses 'GHC.Types.Any' internally to unify (?) unconstrained types, i don't understand much, sorry. > > > >> On Jan 18, 2022, at 8:10 AM, Dmitriy Matrosov wrote: >> >> >> >> On 1/17/22 6:49 PM, Dmitriy Matrosov wrote: >>>> {-# LANGUAGE DataKinds #-} >>>> {-# LANGUAGE RankNTypes #-} >>>> {-# LANGUAGE KindSignatures #-} >>>> {-# LANGUAGE TypeApplications #-} >>>> {-# LANGUAGE TypeOperators #-} >>>> {-# LANGUAGE PolyKinds #-} >>>> {-# LANGUAGE TypeFamilies #-} >>>> {-# LANGUAGE GADTs #-} >>>> {-# LANGUAGE StandaloneKindSignatures #-} >>>> {-# LANGUAGE ScopedTypeVariables #-} >>>> {-# LANGUAGE FlexibleContexts #-} >>>> >>>> import Data.Kind >>>> import Data.Proxy >>>> import Unsafe.Coerce >>>> import qualified GHC.Types as GHC.Types >>>> >>>> class FromTypeMaybe k where >>>> type ToType k >>>> fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) >>>> instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where >>>> --type ToType 'Nothing = GHC.Types.Any >>>> type ToType 'Nothing = t >>>> fromTypeMaybe f _ x = Nothing >>>> instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where >>>> type ToType ('Just t) = t >>>> fromTypeMaybe f _ x = Just (f x) >>> then i've written a little more: >>>> type MaybeHead :: [t] -> Maybe t >>>> type family MaybeHead ts where >>>> MaybeHead '[] = 'Nothing >>>> MaybeHead (x ': xs) = 'Just x >>>> >>>> type Tail:: [t] -> [t] >>>> type family Tail ts where >>>> Tail '[] = '[] >>>> Tail (x ': xs) = xs >>>> >>>> data AnyData where >>>> AnyData :: a -> AnyData >>>> >>>> unAny :: AnyData -> t >>>> unAny (AnyData x) = unsafeCoerce x >>>> >>>> insertAny :: t -> [AnyData] -> [AnyData] >>>> insertAny x zs = AnyData x : zs >>>> >>>> headAny >>>> :: forall ts >>>> . FromTypeMaybe (MaybeHead ts) >>>> => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) >>>> headAny _ [] = Nothing >>>> headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x >>> And now it works, when type-level list is explicitly specified, like: >>> *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] >>> Nothing >>> *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] >>> Just 1 >>> *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] >>> Just 1 >>> but if i use 'Tail' type-function first, it works only in two cases: >>> for list with 2 or more elements >>> *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >>> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >>> :: Maybe Int >>> *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] >>> Just 1 >>> and empty list >>> *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >>> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >>> :: Maybe t >>> *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] >>> Nothing >>> But for list with 1 element it does not work >>> *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >>> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >>> :: Maybe * >>> *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] >>> :246:1: error: >>> • No instance for (Show *) arising from a use of ‘print’ >>> • In a stmt of an interactive GHCi command: print it >>> ..... >>> And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) >>> instance. >> >> I think, i've fixed everything. Eventually, it was very simple. >> >>> {-# LANGUAGE DataKinds #-} >>> {-# LANGUAGE RankNTypes #-} >>> {-# LANGUAGE KindSignatures #-} >>> {-# LANGUAGE TypeApplications #-} >>> {-# LANGUAGE TypeOperators #-} >>> {-# LANGUAGE PolyKinds #-} >>> {-# LANGUAGE TypeFamilies #-} >>> {-# LANGUAGE GADTs #-} >>> {-# LANGUAGE StandaloneKindSignatures #-} >>> {-# LANGUAGE ScopedTypeVariables #-} >>> {-# LANGUAGE FlexibleInstances #-} >>> {-# LANGUAGE MultiParamTypeClasses #-} >>> >>> import Data.Kind >>> import Data.Proxy >>> import Unsafe.Coerce >>> >>> class FromTypeMaybe2 k t where >>> fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t >>> >>> instance FromTypeMaybe2 'Nothing t where >>> fromTypeMaybe2 f _ _ = Nothing >>> >>> instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where >>> fromTypeMaybe2 f _ x = Just (f x) >>> >>> headAny2 >>> :: forall t ts >>> . FromTypeMaybe2 (MaybeHead ts) t >>> => Proxy ts -> [AnyData] -> Maybe t >>> headAny2 _ [] = Nothing >>> headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x >>> >>> type MaybeHead :: [t] -> Maybe t >>> type family MaybeHead ts where >>> MaybeHead '[] = 'Nothing >>> MaybeHead (x ': xs) = 'Just x >>> >>> type Tail:: [t] -> [t] >>> type family Tail ts where >>> Tail '[] = '[] >>> Tail (x ': xs) = xs >>> >>> data AnyData where >>> AnyData :: a -> AnyData >>> >>> unAny :: AnyData -> t >>> unAny (AnyData x) = unsafeCoerce x >> >> And now everything works: >> >> *Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] >> Nothing >> *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] >> Just 1 >> *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] >> Just 1 >> >> and >> >> *Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] >> Just 1 >> *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] >> Nothing >> *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] >> Nothing >> >> The only question, that remains is why defining 'Nothing resulting type to be >> 'GHC.Types.Any' in previous implementation >> >> instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where >> type ToType 'Nothing = GHC.Types.Any >> >> does not fix it? >> _______________________________________________ >> 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 leah at vuxu.org Fri Jan 28 15:05:52 2022 From: leah at vuxu.org (Leah Neukirchen) Date: Fri, 28 Jan 2022 16:05:52 +0100 Subject: [Haskell-cafe] Munich Virtual Haskell Meeting, 2022-01-31 @ 19:30 Message-ID: <87pmobhpdb.fsf@vuxu.org> Dear all, Next week, our monthly Munich Haskell Meeting will take place again on Monday, January 31 on Jitsi at 19:30 CEST. **Due to the pandemic, this meeting will take place online!** For details see here: https://muenchen.haskell.bayern/dates.html A Jitsi link to join the room is provided on the page. 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 carter.schonwald at gmail.com Fri Jan 28 16:45:54 2022 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Fri, 28 Jan 2022 11:45:54 -0500 Subject: [Haskell-cafe] [ANN]: traverse-code In-Reply-To: References: Message-ID: very cool! On Sat, Jan 22, 2022 at 9:33 PM David Feuer wrote: > I've put up a tiny little package[1], traverse-code, offering a > generic way to "traverse" in Template Haskell's `Code m`. > > class TraverseCode t where > traverseCode :: Quote m => (a -> Code m b) -> t a -> Code m (t b) > > I wrote this primarily as a way to "lift" operations on polymorphic > data structures into Template Haskell. For example, for Data.Sequence, > you can write > > triple :: a -> a -> a -> Seq a > triple a b c = $$(sequenceCode $ fromList [ [||a||], [||b||], [||c||] ]) > > The `triple` function will not form its arguments into a list and then > convert it to a sequence; rather, it will build the result sequence > directly, using the underlying constructors. > > A generic default definition is available for all instances of > Generics.Linear.Generic1. See linear-generics[2] for information about > how to derive those. There's nothing particularly linear about > traverse-code, but linear-generics has a more general Generic1 than > GHC.Generics offers. > > [1] https://hackage.haskell.org/package/traverse-code > [2] https://hackage.haskell.org/package/linear-generics > _______________________________________________ > 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 lists at richarde.dev Fri Jan 28 20:48:42 2022 From: lists at richarde.dev (Richard Eisenberg) Date: Fri, 28 Jan 2022 20:48:42 +0000 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: <6d48ca81-edef-9cac-0417-65c6c2713eb7@gmail.com> References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> <010f017e97e5c988-9f08b030-a003-46ec-a0c0-50788fbd5c5c-000000@us-east-2.amazonses.com> <6d48ca81-edef-9cac-0417-65c6c2713eb7@gmail.com> Message-ID: <010f017ea272892d-88e6c08c-9d34-4a14-8cc7-9eb6f1fe03a5-000000@us-east-2.amazonses.com> Thanks. Now I understand much better. > On Jan 27, 2022, at 10:25 AM, Dmitriy Matrosov wrote: > > but when i use 'Tail' function on type-level list with 1 element, it does not > work: > > *Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] > > :22:1: error: > • No instance for (Show *) arising from a use of ‘print’ > • In a stmt of an interactive GHCi command: print it This is all about defaulting. The key question: what is the type of the expression you are typing? - With `headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]`, the type is `Maybe (ToType (MaybeHead (Tail '[Bool])))`. We see that `Tail '[Bool] :: [Type]` reduces to `'[] :: [Type]`. Then, `MaybeHead (Tail '[Bool]) :: Maybe Type` reduces to `Nothing :: Maybe Type`. And finally `ToType (Nothing :: Maybe Type)` reduces to `Type`, meaning that your expression has type `Maybe Type`. Because GHC won't print out something unless it has a Show instance, it bleats, saying there is no Show instance for `Maybe Type`. - Now, consider `headAny @(Tail '[]) Proxy [AnyData 1, AnyData True]`. The result type is `Maybe (ToType (MaybeHead (Tail '[])))`. The point of interest here is: what is the type of `Tail '[]`? It's a list, but the element type is unconstrained. So GHC invents a fresh variable `t`. Following a similar sequence as above, we end up with assigning the expression the type `Maybe t`. At this point, GHC wants to print something of type `Maybe t` but doesn't know what `t` is. It tries `()` as a substitution for `t`. (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html?highlight=extendeddefaultrules#type-defaulting-in-ghci) That works, and the "Nothing" is printed. In other circumstances -- where there is no Show constraint around, for example -- GHC will take an unknown type variable (like t) and default it to GHC.Types.Any. So, you're right that there is no `Show Any` constraint, but GHC doesn't need one, because of its clever (and confusing!) approach to defaulting. Does this help? Richard From mail at joachim-breitner.de Sat Jan 29 11:36:59 2022 From: mail at joachim-breitner.de (Joachim Breitner) Date: Sat, 29 Jan 2022 12:36:59 +0100 Subject: [Haskell-cafe] Request for Nominations to the GHC Steering Committee Message-ID: Dear Haskell community, the GHC Steering committee is seeking nominations for at least two new members. The committee scrutinizes, nitpicks, improves, weights and eventually accepts or rejects proposals that extend or change the language supported by GHC and other (public-facing) aspects of GHC. Our processes are described at https://github.com/ghc-proposals/ghc-proposals which is also the GitHub repository where proposals are proposed. In particular, please have a look at the bylaws at https://github.com/ghc-proposals/ghc-proposals/blob/master/committee.rst We are looking for a member who has the ability * to understand such language extension proposals, * to find holes and missing corner cases in the specifications, * foresee the interaction with other language features and specifications, * comment constructively and improve the proposals, * judge the cost/benefit ratio and * finally come to a justifiable conclusion. We look for committee members who have some of these properties: * have substantial experience in writing Haskell applications or libraries, which they can use to inform judgements about the utility or otherwise of proposed features, * have made active contributions to the Haskell community, for some time, * have expertise in language design and implementation, in either Haskell or related languages, which they can share with us. The committee’s work requires a small, but non-trivial amount of time, especially when you are assigned a proposal for shepherding. We estimate the workload to be around 2 hours per week, and our process works best if members usually respond to technical emails within 1-2 weeks (within days is even better). Please keep that in mind if your email inbox is already overflowing. There is no shortage of people who are eager to get fancy new features into the language, both in the committee and the wider community. But each new feature imposes a cost, to implement, to learn, (particularly) through its unexpected interaction with other features. We need to strike a balance, one that encourages innovation (as GHC always has) while still making Haskell attractive for real-world production use and for teaching. We therefore explicitly invite “conservative” members of the community to join the committee. To make a nomination, please send an email to me (as the committee secretary) at mail at joachim-breitner.de until February 11th. I will distribute the nominations among the committee, and we will keep the nominations and our deliberations private. We explicitly encourage self-nominations. You can nominate others, but please obtain their explicit consent to do so. (We don’t want to choose someone who turns out to be unable to serve.) On behalf of the committee, Joachim Breitner -- Joachim Breitner mail at joachim-breitner.de http://www.joachim-breitner.de/ From sgf.dma at gmail.com Sat Jan 29 11:45:24 2022 From: sgf.dma at gmail.com (Dmitriy Matrosov) Date: Sat, 29 Jan 2022 14:45:24 +0300 Subject: [Haskell-cafe] Coercing existential according to type-level Maybe (re-post from h-beginners) In-Reply-To: <010f017ea272892d-88e6c08c-9d34-4a14-8cc7-9eb6f1fe03a5-000000@us-east-2.amazonses.com> References: <010f017e0c38c22e-30a5eec7-850a-4f1f-af67-1ba48b123d55-000000@us-east-2.amazonses.com> <010f017e2055cda5-c41fc395-7a58-4f0f-9cb2-a197b3806f16-000000@us-east-2.amazonses.com> <0bfc9e89-17e2-a3de-7b20-6b641b4704df@gmail.com> <010f017e97e5c988-9f08b030-a003-46ec-a0c0-50788fbd5c5c-000000@us-east-2.amazonses.com> <6d48ca81-edef-9cac-0417-65c6c2713eb7@gmail.com> <010f017ea272892d-88e6c08c-9d34-4a14-8cc7-9eb6f1fe03a5-000000@us-east-2.amazonses.com> Message-ID: <4c96f8f2-2bcc-4110-fee1-d1e8957c350b@gmail.com> On 1/28/22 11:48 PM, Richard Eisenberg wrote: > >> On Jan 27, 2022, at 10:25 AM, Dmitriy Matrosov wrote: >> >> but when i use 'Tail' function on type-level list with 1 element, it does not >> work: >> >> *Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] >> >> :22:1: error: >> • No instance for (Show *) arising from a use of ‘print’ >> • In a stmt of an interactive GHCi command: print it > > This is all about defaulting. > > The key question: what is the type of the expression you are typing? > > - With `headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]`, the type is `Maybe (ToType (MaybeHead (Tail '[Bool])))`. We see that `Tail '[Bool] :: [Type]` reduces to `'[] :: [Type]`. Then, `MaybeHead (Tail '[Bool]) :: Maybe Type` reduces to `Nothing :: Maybe Type`. And finally `ToType (Nothing :: Maybe Type)` reduces to `Type`, meaning that your expression has type `Maybe Type`. Because GHC won't print out something unless it has a Show instance, it bleats, saying there is no Show instance for `Maybe Type`. > > - Now, consider `headAny @(Tail '[]) Proxy [AnyData 1, AnyData True]`. The result type is `Maybe (ToType (MaybeHead (Tail '[])))`. The point of interest here is: what is the type of `Tail '[]`? It's a list, but the element type is unconstrained. So GHC invents a fresh variable `t`. Following a similar sequence as above, we end up with assigning the expression the type `Maybe t`. At this point, GHC wants to print something of type `Maybe t` but doesn't know what `t` is. It tries `()` as a substitution for `t`. (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html?highlight=extendeddefaultrules#type-defaulting-in-ghci) That works, and the "Nothing" is printed. > > In other circumstances -- where there is no Show constraint around, for example -- GHC will take an unknown type variable (like t) and default it to GHC.Types.Any. So, you're right that there is no `Show Any` constraint, but GHC doesn't need one, because of its clever (and confusing!) approach to defaulting. > > Does this help? > Richard > Yes, thanks! I understand now. From lemming at henning-thielemann.de Sun Jan 30 10:13:15 2022 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun, 30 Jan 2022 11:13:15 +0100 (CET) Subject: [Haskell-cafe] Some Love for wxHaskell In-Reply-To: <9dcdd12a-9b9a-a6f1-65c8-24f912130daa@gmx.de> References: <9dcdd12a-9b9a-a6f1-65c8-24f912130daa@gmx.de> Message-ID: On Mon, 19 Apr 2021, Tilmann wrote: > Thank you all for sharing, this was really helpful for me to clear my mind Any updates on this? I just noticed that wxhaskell cannot be build with cabal v2-build or ghc>=8.4. From johannes.waldmann at htwk-leipzig.de Sun Jan 30 16:46:44 2022 From: johannes.waldmann at htwk-leipzig.de (Johannes Waldmann) Date: Sun, 30 Jan 2022 17:46:44 +0100 Subject: [Haskell-cafe] how to set extra-lib-dirs for a dependency in a stack project? Message-ID: <580bf1f7-2f5e-14a8-601f-57cf558112b6@htwk-leipzig.de> Dear Cafe, is it possible to specify include-dirs and extra-lib-dirs for a dependency? I have * top-level project A, depends on: * project B, depends on: * C: external library (written in C) I am building A with stack. I don't want to put fixed locations (include/lib) for C in B.cabal, because it depends on the (top-level) build environment of A (e.g., my machine, or CI). Concrete example: C = kissat SAT solver, B = Haskell API for C. I know that, e.g., https://hackage.haskell.org/package/minisat works around this problem by vendoring (is this the word?) the solver's code (into B). I don't want this. With cabal.project, I could set options for (all?) dependencies? https://cabal.readthedocs.io/en/3.4/cabal-project.html#foreign-function-interface-options Would stack use this setting (will it read that file at all)? Will I have to copy all extra-deps source repo locations to cabal.project? - J. From lemming at henning-thielemann.de Sun Jan 30 17:05:56 2022 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun, 30 Jan 2022 18:05:56 +0100 (CET) Subject: [Haskell-cafe] how to set extra-lib-dirs for a dependency in a stack project? In-Reply-To: <580bf1f7-2f5e-14a8-601f-57cf558112b6@htwk-leipzig.de> References: <580bf1f7-2f5e-14a8-601f-57cf558112b6@htwk-leipzig.de> Message-ID: <943d877b-e6cb-d684-a628-7ff40b9c549@henning-thielemann.de> On Sun, 30 Jan 2022, Johannes Waldmann wrote: > is it possible to specify include-dirs and extra-lib-dirs > for a dependency? > > I have > > * top-level project A, depends on: > * project B, depends on: > * C: external library (written in C) > > I am building A with stack. I don't want to put > fixed locations (include/lib) for C in B.cabal, > because it depends on the (top-level) build environment of A > (e.g., my machine, or CI). > > Concrete example: C = kissat SAT solver, B = Haskell API for C. Are B and C part of Stackage? It sounds as if they are not. If so, then why would you want to build with 'stack', at all? > With cabal.project, I could set options for (all?) dependencies? > https://cabal.readthedocs.io/en/3.4/cabal-project.html#foreign-function-interface-options > Would stack use this setting (will it read that file at all)? stack ignores cabal.project. > Will I have to copy all extra-deps source repo locations > to cabal.project? In cabal.project you can add: package C extra-include-dirs: /usr/local/C/include extra-lib-dirs: /usr/local/C/lib From johannes.waldmann at htwk-leipzig.de Sun Jan 30 17:28:55 2022 From: johannes.waldmann at htwk-leipzig.de (Johannes Waldmann) Date: Sun, 30 Jan 2022 18:28:55 +0100 Subject: [Haskell-cafe] how to set extra-lib-dirs for a dependency in a stack project? In-Reply-To: <943d877b-e6cb-d684-a628-7ff40b9c549@henning-thielemann.de> References: <580bf1f7-2f5e-14a8-601f-57cf558112b6@htwk-leipzig.de> <943d877b-e6cb-d684-a628-7ff40b9c549@henning-thielemann.de> Message-ID: Hi. > In cabal.project you can add: > > package C > extra-include-dirs: /usr/local/C/include > extra-lib-dirs: /usr/local/C/lib yes. That way I can build with cabal only (not stack) and I need to copy all my extra source repo locations from stack.yaml to cabal.project (and then need to maintain both files)OK, it's an option that I will consider. > Are B and C part of Stackage? > > It sounds as if they are not. > > If so, then why would you want to build with 'stack', at all? A has lots of other dependencies. For specifying their versions, I'd like to rely on stackage's resolver. - J. From lemming at henning-thielemann.de Sun Jan 30 17:35:17 2022 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun, 30 Jan 2022 18:35:17 +0100 (CET) Subject: [Haskell-cafe] how to set extra-lib-dirs for a dependency in a stack project? In-Reply-To: References: <580bf1f7-2f5e-14a8-601f-57cf558112b6@htwk-leipzig.de> <943d877b-e6cb-d684-a628-7ff40b9c549@henning-thielemann.de> Message-ID: On Sun, 30 Jan 2022, Johannes Waldmann wrote: >> In cabal.project you can add: >> >> package C >> extra-include-dirs: /usr/local/C/include >> extra-lib-dirs: /usr/local/C/lib > > yes. That way I can build with cabal only (not stack) > and I need to copy all my extra source repo locations > from stack.yaml to cabal.project > (and then need to maintain both files)OK, it's an option that I will > consider. You may consider putting extra-lib-dirs paths in your .cabal/config . From olf at aatal-apotheke.de Mon Jan 31 20:10:25 2022 From: olf at aatal-apotheke.de (Olaf Klinke) Date: Mon, 31 Jan 2022 21:10:25 +0100 Subject: [Haskell-cafe] [ANN] opc-xml-da-client, a client for the OPC XML-DA protocol Message-ID: <3703d967fa450377a568d3483e08fe33c325ae88.camel@aatal-apotheke.de> Dear Haskell Café, I am pleased to announce opc-xml-da-client [1,2], an implementation of (the client side of) the OPC XML-DA data access protocol. While the OPC XML-DA protocol is quite dated (2003) and has largely been superseded by other OPC flavours, it is still being used in industrial environments. OPC XML-DA is based on SOAP and the data types in the Haskell package closely reflect the protocol specification as a web services description language document [5]. This package was developed by Mlabs [3] as contract work for my employer. We release it as FOSS, with Mlabs kindly hosting the project under their Github account. To my knowledge, besides PyOPC [4] this is the only freely available OPC XML-DA library and the only Haskell OPC library. We stopped using PyOPC because Python hit performance limits while parsing the XML. Feel free to contact me or Nikita Volkov at Mlabs if you have further questions. Cheers Olaf [1] https://github.com/mlabs-haskell/opc-xml-da-client [2] https://hackage.haskell.org/package/opc-xml-da-client [3] https://mlabs.city [4] https://pypi.org/project/PyOPC/ [5] https://opcfoundation.org/XMLDA/1.0/OpcXmlDa1.00.wsdl From benjamin.redelings at gmail.com Mon Jan 31 22:50:57 2022 From: benjamin.redelings at gmail.com (Benjamin Redelings) Date: Mon, 31 Jan 2022 14:50:57 -0800 Subject: [Haskell-cafe] Explicit type signatures and wrappers / impedance-matching Message-ID: <69bf561f-2fea-d1dd-4485-75e7dcbe28de@gmail.com> Hi, I am trying to understand (and implement) how Haskell handles explicit type signatures.  Specifically, I'm trying to understand how explicit type signatures interact with wrappers. 1. Is there any paper or documentation that explains wrappers and/or explicit type signatures in detail?  There are some non-obvious details regarding wrappers, such as using eliminating type arguments by supplying the Any type as an argument... 2. Do explicit type signatures impose any unification constraints, or can they be thought of entirely in terms of wrappers? For example, if we have g :: Int -> Int (f,g) = (\x ->x, f) then the signature for g is added to the environment when typing the right-hand-side. One way that this could be handled is: (i) typecheck rhs -> rhs_type (ii) generate type of lhs with fresh variables for every binder -> lhs_type = (a,b) (iii) unify(lhs_type, rhs_type) (iv) do one-way unification: match(inferred-type-of-g, explicit-type-for-g) Is this correct?  Step (iv), the way that I have written it, would impose unification constraints. Without considering the type signature, we would have { f_mono :: a -> a, g_mono :: a -> a} If we just use wrappers to impose the explict type, it seems like we would get something like let tup = /\a.let {(f:a,g:a) = (\x:a -> x:a, f::a->a) f = /\a.case tup a of (f,g) -> f g = case tup @Int of (f,g) -> g where f :: forall a.a ->a and g :: Int -> Int. THIH seems to imply that type signatures are merely checked: no unification constraints are imposed (I think).  However, ghc reports f :: Int -> Int. I apologize if this is a dumb question.  I have found the definition of HsWrapper in ghc/compiler/GHC/Tc/Types/Evidence.hs, but I am still struggling a bit. thanks! -BenRI -------------- next part -------------- An HTML attachment was scrubbed... URL: