[GHC] #8165: Use GeneralizedNewtypeDeriving to automatically create associated type families

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families ------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Keywords: | Operating System: Unknown/Multiple Architecture: Unknown/Multiple | Type of failure: None/Unknown Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | ------------------------------------+------------------------------------- Here's a simple example: {{{ class C a where type T a instance C Int where type T Int = Bool newtype NT = NT Int deriving C }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------ Reporter: MikeIzbicki | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by goldfire): What should happen in this scenario: {{{ class D a where type U a instance D Int where type U Int = Int newtype E = MkE Int deriving D }}} What does `U E` reduce to, `E` or `Int`? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------ Reporter: MikeIzbicki | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by MikeIzbicki): Ambiguous cases like this could remain a type error. That would probably prevent the most confusion. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------ Reporter: MikeIzbicki | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by MikeIzbicki): In all the cases where I've wanted to use this, the type is polymorphic. Here's a real example of when I've wanted to use this: {{{ class HasRing a where type Ring a instance HasRing [a] where type Ring [a] = a instance Hasring (Vector a) where type Ring (Vector a) = a newtype L2Norm a = L2Norm a deriving HasRing newtype L1Norm a = L1Norm a deriving HasRing }}} The deriving clauses would be equivalent to: {{{ instance HasRing a => HasRing (L2Norm a) where type Ring (L2Norm a) = Ring a instance HasRing a => HasRing (L1Norm a) where type Ring (L1Norm a) = Ring a }}} This might become problematic if there are multiple type parameters though. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------ Reporter: MikeIzbicki | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by goldfire): This auto-generation seems to be rather different from the way `GeneralizedNewtypeDeriving` works in other contexts. In particular, the instances that you're generating are not directly related to any existing instances. Are you proposing that type families used on derived instances should just "look through" the newtype and be applied to the base type? Or only in cases with type variables? And, where does the `HasRing a =>` constraint come from? Without those constraints, I can see more of a coherent and general picture here... but it doesn't seem like `GeneralizedNewtypeDeriving` to me. Perhaps you're really proposing a new extension for generation of type family instances for newtypes? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: | Owner: MikeIzbicki | Status: new Type: feature | Milestone: request | Version: 7.6.3 Priority: normal | Keywords: Component: Compiler | Architecture: Unknown/Multiple (Type checker) | Difficulty: Unknown Resolution: | Blocked By: Operating System: | Related Tickets: Unknown/Multiple | Type of failure: | None/Unknown | Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Changes (by thomie): * component: Compiler => Compiler (Type checker) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler (Type | Version: 7.6.3 checker) | Keywords: Resolution: | Architecture: Operating System: Unknown/Multiple | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by goldfire): * owner: => goldfire * milestone: => 7.12.1 Comment: Encouraged by Iavor Diatchki and Adam Gundry, I've realized that my comment:4 is utterly wrong -- !MikeIzbicki's proposal is reasonable. Concretely, I propose: * `GeneralizedNewtypeDeriving` for classes with associated types define new associated type instances that "look through" to the underlying type instance. This satisfies Mike's original example. To my comment:1, it says `Int`. And, this proposal works for comment:3. Note that associated `data` instances will still be prohibited -- these are not covered by this ticket. I can implement in due course. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler (Type | Version: 7.6.3 checker) | Keywords: Resolution: | Architecture: Operating System: Unknown/Multiple | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): So, to be more specific, the recipe is this: {{{ class C a where type T a op :: a -> a newtype T a = MkT <rep-type> deriving( C ) }}} Here the `deriving` clause would generate {{{ instance C <rep-type> => C (T a) where type T (T a) = T <rep-type> op = coerce (op :: <rep-type> -> <rep-type>) }}} As usual, a wiki page to explain the details when we have to eta-reduce the newtype, etc, would be helpful. Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Would this approach be able to work for associated injective type families? If you had something like this: {{{#!hs class C a where type T a = r | r -> a instance C Int where type T Int = Char newtype WrappedInt = WrapInt Int deriving C }}} Then, if I understand the above proposal, the following code would be generated: {{{#!hs instance C WrappedInt where type T WrappedInt = T Int }}} which would violate injectivity. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by goldfire): * milestone: 8.0.1 => 8.2.1 Comment: Yes, as well it should. Derived instances are still type-checked, so this would be caught with no special-casing. I could imagine that the error message would be hard to understand, but that's the worst that would happen. But this isn't going to happen by the 8.0 feature freeze, I'm afraid. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * cc: RyanGlScott (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * related: => #2721 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Hm... what code would generated in this example? {{{#!hs {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} import Data.Kind class C (a :: k) where type T k :: Type instance C Int where type T Type = Int -------------------- newtype MyInt = MyInt Int deriving C }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by rwbarton): The definition of `C` should be illegal since it doesn't mention the variable `a`. Apparently that hasn't been fixed yet though, I thought it was? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:15 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Why should `C` be illegal? The type parameters of `T` are a permutation of a proper subset of the class parameters (`a` and `k`), so it [https://wiki.haskell.org/GHC/Type_families#Associated_family_declarations_2 should be legal]. But moreover, I think the answer to my question in comment:14 is: you can't newtype-derive `C` for `MyInt`, as there's an associated type that //doesn't mention the last type parameter of `C`//. This is crucial, because if this doesn't hold, then we won't have a `T` instance to fall back on, making the whole derivation crumble. We'd just need to check for this condition beforehand. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by rwbarton): Oh that is a strange condition, but okay. (Maybe what I was thinking about was a new sanity condition on associated type instances, not their declarations.) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: goldfire Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): The recipe gave in comment:4 doesn't work for the example in comment:14. I could elaborate the recipe a bit thus: {{{ class C x y z where type T y z x op :: x -> [y] -> z newtype N a = MkN <rep-type> deriving( C ) -- Here the deriving clause would generate instance C x y <rep-type> => C x y (N a) where type T y (N a) x = T y <rep-type> x op = coerce (op :: x -> [y] -> <rep-type>) }}} The recipe for generating the `type instance` is to replace the occurrence of `z` (which must occur) with `<rep-type>` on the LHS and RHS. I don't think it need be the last parameter of `T`, as the example shows. I'm far from sure if this is really worth the effort of explaining and implementing it. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:18 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * owner: goldfire => RyanGlScott Comment: Right, I didn't say the last type parameter of `T` had to be the newtype. Rather, the last type parameter of the class `C` (`z` in the example in comment:18) just has to occur somewhere in the type parameters of `T`.
I'm far from sure if this is really worth the effort of explaining and implementing it.
I disagree! Really, this is a quite straightforward idea (with a couple of small gotchas, like the one you observed), and I've implemented most of it already—I just need to polish up the documentation, update the GHC wiki, and post a Phabricator Diff. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:19 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by goldfire): Just to be clear on the design here: we plan on rejecting the code in comment:14, right? That is, for GND to work with associated types, the last parameter of the class must be mentioned in the associated type LHS. Then I'm on board. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:20 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Replying to [comment:20 goldfire]:
Just to be clear on the design here: we plan on rejecting the code in comment:14, right? That is, for GND to work with associated types, the last parameter of the class must be mentioned in the associated type LHS. Then I'm on board.
Yes, precisely. I'll make sure to mention this fact in the users' guide. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:21 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: patch Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Phab:D2636 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => patch * differential: => Phab:D2636 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:22 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type
families
-------------------------------------+-------------------------------------
Reporter: MikeIzbicki | Owner: RyanGlScott
Type: feature request | Status: patch
Priority: normal | Milestone: 8.2.1
Component: Compiler (Type | Version: 7.6.3
checker) |
Resolution: | Keywords: TypeFamilies
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: #2721 | Differential Rev(s): Phab:D2636
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ryan Scott

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Resolution: fixed | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: | deriving/should_compile/T8165, | deriving/should_fail/T8165_fail1, | deriving/should_fail/T8165_fail2 Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Phab:D2636 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * testcase: => deriving/should_compile/T8165, deriving/should_fail/T8165_fail1, deriving/should_fail/T8165_fail2 * status: patch => closed * resolution: => fixed -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:24 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8165: Use GeneralizedNewtypeDeriving to automatically create associated type families -------------------------------------+------------------------------------- Reporter: MikeIzbicki | Owner: RyanGlScott Type: feature request | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.6.3 checker) | Keywords: TypeFamilies, Resolution: fixed | deriving Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: | deriving/should_compile/T8165, | deriving/should_fail/T8165_fail1, | deriving/should_fail/T8165_fail2 Blocked By: | Blocking: Related Tickets: #2721 | Differential Rev(s): Phab:D2636 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: TypeFamilies => TypeFamilies, deriving -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8165#comment:25 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC