Unfortunately the old class based solution also carries other baggage, like the old data type contexts being needed in the language for bang patterns. :(
-Edward > On Apr 1, 2014, at 5:26 PM, John Lato <jwl...@gmail.com> wrote: > > Hi Edward, > > Yes, I'm aware of that. However, I thought Dan's proposal especially droll > given that changing seq to a class-based function would be sufficient to make > eta-reduction sound, given appropriate instances (or lack thereof). Meaning > we could leave the rest of the proposal unevaluated (lazily!). > > And if somebody were to suggest that on a different day, +1 from me. > > John > >> On Apr 1, 2014 10:32 AM, "Edward Kmett" <ekm...@gmail.com> wrote: >> John, >> >> Check the date and consider the process necessary to "enumerate all Haskell >> programs and check their types". >> >> -Edward >> >> >>> On Tue, Apr 1, 2014 at 9:17 AM, John Lato <jwl...@gmail.com> wrote: >>> I think this is a great idea and should become a top priority. I would >>> probably start by switching to a type-class-based seq, after which perhaps >>> the next step forward would become more clear. >>> >>> John L. >>> >>>> On Apr 1, 2014 2:54 AM, "Dan Doel" <dan.d...@gmail.com> wrote: >>>> In the past year or two, there have been multiple performance problems in >>>> various areas related to the fact that lambda abstraction is not free, >>>> though we >>>> tend to think of it as so. A major example of this was deriving of >>>> Functor. If we >>>> were to derive Functor for lists, we would end up with something like: >>>> >>>> instance Functor [] where >>>> fmap _ [] = [] >>>> fmap f (x:xs) = f x : fmap (\y -> f y) xs >>>> >>>> This definition is O(n^2) when fully evaluated,, because it causes O(n) eta >>>> expansions of f, so we spend time following indirections proportional to >>>> the >>>> depth of the element in the list. This has been fixed in 7.8, but there are >>>> other examples. I believe lens, [1] for instance, has some stuff in it that >>>> works very hard to avoid this sort of cost; and it's not always as easy to >>>> avoid >>>> as the above example. Composing with a newtype wrapper, for instance, >>>> causes an >>>> eta expansion that can only be seen as such at the core level. >>>> >>>> The obvious solution is: do eta reduction. However, this is not >>>> operationally >>>> sound currently. The problem is that seq is capable of telling the >>>> difference >>>> between the following two expressions: >>>> >>>> undefined >>>> \x -> undefined x >>>> >>>> The former causes seq to throw an exception, while the latter is considered >>>> defined enough to not do so. So, if we eta reduce, we can cause terminating >>>> programs to diverge if they make use of this feature. >>>> >>>> Luckily, there is a solution. >>>> >>>> Semantically one would usually identify the above two expressions. While I >>>> do >>>> believe one could construct a semantics that does distinguish them, it is >>>> not >>>> the usual practice. This suggests that there is a way to not distinguish >>>> them, >>>> perhaps even including seq. After all, the specification of seq is >>>> monotone and >>>> continuous regardless of whether we unify ⊥ with \x -> ⊥ x or insert an >>>> extra >>>> element for the latter. >>>> >>>> The currently problematic case is function spaces, so I'll focus on it. How >>>> should: >>>> >>>> seq : (a -> b) -> c -> c >>>> >>>> act? Well, other than an obvious bottom, we need to emit bottom whenever >>>> our >>>> given function is itself bottom at every input. This may first seem like a >>>> problem, but it is actually quite simple. Without loss of generality, let >>>> us >>>> assume that we can enumerate the type a. Then, we can feed these values to >>>> the >>>> function, and check their results for bottom. Conal Elliot has prior art >>>> for >>>> this sort of thing with his unamb [2] package. For each value x :: a, >>>> simply >>>> compute 'f x `seq` ()' in parallel, and look for any successes. If we ever >>>> find >>>> one, we know the function is non-bottom, and we can return our value of c. >>>> If we >>>> never finish searching, then the function must be bottom, and seq should >>>> not >>>> terminate, so we have satisfied the specification. >>>> >>>> Now, some may complain about the enumeration above. But this, too, is a >>>> simple >>>> matter. It is well known that Haskell programs are denumerable. So it is >>>> quite >>>> easy to enumerate all Haskell programs that produce a value, check whether >>>> that >>>> value has the type we're interested in, and compute said value. All of >>>> this can >>>> be done in Haskell. Thus, every Haskell type is programatically enumerable >>>> in >>>> Haskell, and we can use said enumeration in our implementation of seq for >>>> function types. I have discussed this with Russell O'Connor [3], and he >>>> assures >>>> me that this argument should be sufficient even if we consider semantic >>>> models >>>> of Haskell that contain values not denoted by any Haskell program, so we >>>> should >>>> be safe there. >>>> >>>> The one possible caveat is that this implementation of seq is not >>>> operationally >>>> uniform across all types, so the current fully polymorphic type of seq may >>>> not >>>> make sense. But moving back to a type class based approach isn't so bad, >>>> and >>>> this time we will have a semantically sound backing, instead of just >>>> having a >>>> class with the equivalent of the current magic function in it. >>>> >>>> Once this machinery is in place, we can eta reduce to our hearts' content, >>>> and >>>> not have to worry about breaking semantics. We'd no longer put the burden >>>> on >>>> programmers to use potentially unsafe hacks to avoid eta expansions. I >>>> apologize >>>> for not sketching an implementation of the above algorithm, but I'm sure it >>>> should be elementary enough to make it into GHC in the next couple >>>> versions. >>>> Everyone learns about this type of thing in university computer science >>>> programs, no? >>>> >>>> Thoughts? Comments? Questions? >>>> >>>> Cheers, >>>> -- Dan >>>> >>>> [1] http://hackage.haskell.org/package/lens >>>> [2] http://hackage.haskell.org/package/unamb >>>> [3] http://r6.ca/ >>>> >>>> >>>> _______________________________________________ >>>> Glasgow-haskell-users mailing list >>>> Glasgow-haskell-users@haskell.org >>>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> haskell-c...@haskell.org >>> http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users