Re: [Haskell-cafe] Overriding a Prelude function?
OK, I changed the operator from (>>) to (~>>). When I try to use it I get this: [michael@localhost ~]$ ghci rand GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. [1 of 1] Compiling Main ( rand.hs, interpreted ) Ok, modules loaded: Main. *Main> rollDie ~>> (rollDie ~>> rollDie) <interactive>:1:0: No instance for (Show (Seed -> (Int, Seed))) arising from a use of `print' at <interactive>:1:0-32 Possible fix: add an instance declaration for (Show (Seed -> (Int, Seed))) In a stmt of a 'do' expression: print it *Main> Michael --- On Wed, 4/22/09, Luke Palmer <lrpalmer@gmail.com> wrote: From: Luke Palmer <lrpalmer@gmail.com> Subject: Re: [Haskell-cafe] Overriding a Prelude function? To: "michael rice" <nowgate@yahoo.com> Cc: "Ross Mellgren" <rmm-haskell@z.odi.ac>, "Dan Weston" <westondan@imageworks.com>, "haskell-cafe@haskell.org" <haskell-cafe@haskell.org> Date: Wednesday, April 22, 2009, 5:02 PM On Wed, Apr 22, 2009 at 1:47 PM, michael rice <nowgate@yahoo.com> wrote: Here's what I get: [michael@localhost ~]$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude> import Prelude hiding ((>>)) You know, to avoid this nonsense you could just name the operator something else, like >>~, or ~>>, or $@**!. Operators are just names. Luke <interactive>:1:0: parse error on input `import' Prelude> ===== I was passing seed0 to rollDie and getting back (r1,seed1) passing seed1 to rollDie and getting back (r2,seed2) passing seed2 to rollDie and getting back (r3,seed3) Just based on the problem text, I would guess that passing rollDie and seed0 to (>>) I would get back (r3,seed3), losing the intermediate random numbers r1 and r2 along the way, at least that's what I understood it to say. So, I know that next I'm probably going to have to do something to remedy that, but I haven't gotten to that next step yet. What is unsugar? Thanks in advance for your patience. Michael --- On Wed, 4/22/09, Dan Weston <westondan@imageworks.com> wrote: From: Dan Weston <westondan@imageworks.com> Subject: Re: [Haskell-cafe] Overriding a Prelude function? To: "Ross Mellgren" <rmm-haskell@z.odi.ac> Cc: "michael rice" <nowgate@yahoo.com>, "haskell-cafe@haskell.org" <haskell-cafe@haskell.org> Date: Wednesday, April 22, 2009, 12:37 PM Be aware that the do unsugars to (Prelude.>>), not your (>>), even if you hide (Prelude.>>): import Prelude hiding ((>>)) m >> f = error "Call me!" main = putStrLn . show $ do [3,4] [5] The desugaring of the do { [3,4]; [5] } is (Prelude.>>) [3,4] [5] = [5,5], whereas you might have hoped for [3,4] >> [5] = error "Call me!" Dan Ross Mellgren wrote:
I think
import Prelude hiding ((>>))
does that.
-Ross
On Apr 22, 2009, at 11:44 AM, michael rice wrote:
I've been working through this example from: http://en.wikibooks.org/wiki/Haskell/Understanding_monads
I understand what they're doing all the way up to the definition of (>>), which duplicates Prelude function (>>). To continue following the example, I need to know how to override the Prelude (>>) with the (>>) definition in my file rand.hs.
Michael
==============
[michael@localhost ~]$ cat rand.hs import System.Random
type Seed = Int
randomNext :: Seed -> Seed randomNext rand = if newRand > 0 then newRand else newRand + 2147483647
where newRand = 16807 * lo - 2836 * hi (hi,lo) = rand `divMod` 127773
toDieRoll :: Seed -> Int toDieRoll seed = (seed `mod` 6) + 1
rollDie :: Seed -> (Int, Seed) rollDie seed = ((seed `mod` 6) + 1, randomNext seed)
sumTwoDice :: Seed -> (Int, Seed) sumTwoDice seed0 = let (die1, seed1) = rollDie seed0 (die2, seed2) = rollDie seed1 in (die1 + die2, seed2)
(>>) m n = \seed0 ->
let (result1, seed1) = m seed0 (result2, seed2) = n seed1 in (result2, seed2)
[michael@localhost ~]$
_______________________________________________
Haskell-Cafe mailing list Haskell-Cafe@haskell.org <mailto:Haskell-Cafe@haskell.org>
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
michael rice <nowgate@yahoo.com> wrote:
OK, I changed the operator from (>>) to (~>>). When I try to use it I get this:
[michael@localhost ~]$ ghci rand GHCi, version 6.10.1: http://www.haskell.org/ghc/__ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. [1 of 1] Compiling Main________________________ ( rand.hs, interpreted ) Ok, modules loaded: Main. *Main> rollDie ~>> (rollDie ~>> rollDie)
<interactive>:1:0: ______ No instance for (Show (Seed -> (Int, Seed))) __________ arising from a use of `print' at <interactive>:1:0-32 ______ Possible fix: __________ add an instance declaration for (Show (Seed -> (Int, Seed))) ______ In a stmt of a 'do' expression: print it
Well, you obviously need an initial seed: rollDie 0xdeadbeef ~>> (rollDie ~>> rollDie) -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.
Achim Schneider wrote:
Well, you obviously need an initial seed:
rollDie 0xdeadbeef ~>> (rollDie ~>> rollDie)
Achim means (rollDie ~>> (rollDie ~>> rollDie)) 0xdeadbeef Regards, apfelmus -- http://apfelmus.nfshost.com
*Main> :t rollDie ~>> (rollDie ~>> rollDie) rollDie ~>> (rollDie ~>> rollDie) :: Seed -> (Int, Seed) This is a function. How exactly do you want ghci to show it? When you figure that out, feel free to make an instance of Show for it. Meanwhile, you can just apply the function to a Seed value and see what happens: *Main> rollDie ~>> rollDie ~>> rollDie $ 6 (1,1145965850) michael rice wrote:
OK, I changed the operator from (>>) to (~>>). When I try to use it I get this:
[michael@localhost ~]$ ghci rand GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. [1 of 1] Compiling Main ( rand.hs, interpreted ) Ok, modules loaded: Main. *Main> rollDie ~>> (rollDie ~>> rollDie)
<interactive>:1:0: No instance for (Show (Seed -> (Int, Seed))) arising from a use of `print' at <interactive>:1:0-32 Possible fix: add an instance declaration for (Show (Seed -> (Int, Seed))) In a stmt of a 'do' expression: print it *Main>
Michael
--- On *Wed, 4/22/09, Luke Palmer /<lrpalmer@gmail.com>/* wrote:
From: Luke Palmer <lrpalmer@gmail.com> Subject: Re: [Haskell-cafe] Overriding a Prelude function? To: "michael rice" <nowgate@yahoo.com> Cc: "Ross Mellgren" <rmm-haskell@z.odi.ac>, "Dan Weston" <westondan@imageworks.com>, "haskell-cafe@haskell.org" <haskell-cafe@haskell.org> Date: Wednesday, April 22, 2009, 5:02 PM
On Wed, Apr 22, 2009 at 1:47 PM, michael rice <nowgate@yahoo.com </mc/compose?to=nowgate@yahoo.com>> wrote:
Here's what I get:
[michael@localhost ~]$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude> import Prelude hiding ((>>))
You know, to avoid this nonsense you could just name the operator something else, like >>~, or ~>>, or $@**!. Operators are just names.
Luke
<interactive>:1:0: parse error on input `import' Prelude>
=====
I was passing seed0 to rollDie and getting back (r1,seed1) passing seed1 to rollDie and getting back (r2,seed2) passing seed2 to rollDie and getting back (r3,seed3)
Just based on the problem text, I would guess that passing rollDie and seed0 to (>>) I would get back (r3,seed3), losing the intermediate random numbers r1 and r2 along the way, at least that's what I understood it to say.
So, I know that next I'm probably going to have to do something to remedy that, but I haven't gotten to that next step yet. What is unsugar?
Thanks in advance for your patience.
Michael
--- On *Wed, 4/22/09, Dan Weston /<westondan@imageworks.com </mc/compose?to=westondan@imageworks.com>>/* wrote:
From: Dan Weston <westondan@imageworks.com </mc/compose?to=westondan@imageworks.com>> Subject: Re: [Haskell-cafe] Overriding a Prelude function? To: "Ross Mellgren" <rmm-haskell@z.odi.ac </mc/compose?to=rmm-haskell@z.odi.ac>> Cc: "michael rice" <nowgate@yahoo.com </mc/compose?to=nowgate@yahoo.com>>, "haskell-cafe@haskell.org </mc/compose?to=haskell-cafe@haskell.org>" <haskell-cafe@haskell.org </mc/compose?to=haskell-cafe@haskell.org>> Date: Wednesday, April 22, 2009, 12:37 PM
Be aware that the do unsugars to (Prelude.>>), not your (>>), even if you hide (Prelude.>>):
import Prelude hiding ((>>)) m >> f = error "Call me!" main = putStrLn . show $ do [3,4] [5]
The desugaring of the do { [3,4]; [5] } is (Prelude.>>) [3,4] [5] = [5,5], whereas you might have hoped for [3,4] >> [5] = error "Call me!"
Dan
Ross Mellgren wrote: > I think > > import Prelude hiding ((>>)) > > does that. > > -Ross > > On Apr 22, 2009, at 11:44 AM, michael rice wrote: > >> I've been working through this example from: http://en.wikibooks.org/wiki/Haskell/Understanding_monads >> >> I understand what they're doing all the way up to the definition of (>>), which duplicates Prelude function (>>). To continue following the example, I need to know how to override the Prelude (>>) with the (>>) definition in my file rand.hs. >> >> Michael >> >> ============== >> >> [michael@localhost ~]$ cat rand.hs >> import System.Random >> >> type Seed = Int >> >> randomNext :: Seed -> Seed >> randomNext rand = if newRand > 0 then newRand else newRand + 2147483647 >> where newRand = 16807 * lo - 2836 * hi >> (hi,lo) = rand `divMod` 127773 >> >> toDieRoll :: Seed -> Int >> toDieRoll seed = (seed `mod` 6) + 1 >> >> rollDie :: Seed -> (Int, Seed) >> rollDie seed = ((seed `mod` 6) + 1, randomNext seed) >> >> sumTwoDice :: Seed -> (Int, Seed) >> sumTwoDice seed0 = >> let (die1, seed1) = rollDie seed0 >> (die2, seed2) = rollDie seed1 >> in (die1 + die2, seed2) >> >> (>>) m n = \seed0 -> >> let (result1, seed1) = m seed0 >> (result2, seed2) = n seed1 >> in (result2, seed2) >> >> [michael@localhost ~]$ >> >> >> _______________________________________________ >> Haskell-Cafe mailing list >> Haskell-Cafe@haskell.org <http://mc/compose?to=Haskell-Cafe@haskell.org> <mailto:Haskell-Cafe@haskell.org <http://mc/compose?to=Haskell-Cafe@haskell.org>>
>> http://www.haskell.org/mailman/listinfo/haskell-cafe >
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org </mc/compose?to=Haskell-Cafe@haskell.org> http://www.haskell.org/mailman/listinfo/haskell-cafe
*Main> :t rollDie ~>> (rollDie ~>> rollDie) rollDie ~>> (rollDie ~>> rollDie) :: Seed -> (Int, Seed)
This is a function. How exactly do you want ghci to show it? When you figure that out, feel free to make an instance of Show for it.
Just because user programs can't show function internals (they can show parts of in/out tables, and with sufficient overloading they can even show approximations of representation) that does not mean that the language implementation can't show function internals. That is a feature that I've always missed in Haskell implementations. In the reduction systems I used before Haskell, one could enter a function, reduce it (stepwise, or to whnf, or even to hnf) and get the resulting function back in the editor, ready for inspection, editing, application, and further reduction. That kind of feature needs to be designed into the implementation early on, but it gives a whole new dimension to "programming with functions" (I recall how difficult it was for the designers and implementers of those reduction systems to explain that difference to reviewers). Claus PS. and, yes, before anyone suspects otherwise, those reduction systems did compiled graph reduction - they just didn't expose users to all those low-level details.
On 23 Apr 2009, at 23:07, Claus Reinke wrote:
*Main> :t rollDie ~>> (rollDie ~>> rollDie) rollDie ~>> (rollDie ~>> rollDie) :: Seed -> (Int, Seed) This is a function. How exactly do you want ghci to show it? When you figure that out, feel free to make an instance of Show for it.
Just because user programs can't show function internals (they can show parts of in/out tables, and with sufficient overloading they can even show approximations of representation) that does not mean that the language implementation can't show function internals.
Well, than, what would you expect from this: let {f x = g x; g 0 = 0; g n = f (n-1)} in show f ?
On Thu, Apr 23, 2009 at 1:34 PM, Miguel Mitrofanov <miguelimo38@yandex.ru>wrote:
Well, than, what would you expect from this:
let {f x = g x; g 0 = 0; g n = f (n-1)} in show f
Well, not show, because any show instance for functions breaks r.t. But the interactive interpreter, if it is not subject to r.t., might show: let { f x = g x; g 0 = 0; g n = f (n-1) } in f Or fst (fix (\~(f,g) -> (\x -> g x, \n -> case n of { 0 -> 0; n -> f (n-1) }))) Or any number of other equivalent writings. Luke
Well, than, what would you expect from this:
let {f x = g x; g 0 = 0; g n = f (n-1)} in show f
Well, not show, because any show instance for functions breaks r.t. But the interactive interpreter, if it is not subject to r.t., might show:
let { f x = g x; g 0 = 0; g n = f (n-1) } in f
Actually, most of those reduction systems were strongly, but dynamically typed, so the original example would give something like this (no reductions possible): let {f x = g x; g 0 = 0; g n = f (n-1)} in show f And if you applied something like 'show' to something it can work with (let's wrap it in a function to make things interesting), \x->show [1,2] you might get, unsurprisingly (but watch your representation levels!) \x->"[1,2]" As far as referential transparency is concerned, you'd need to keep your reference levels straight, which can seem confusing if you can only communicate via representations(*:-) The easy part is semantics and inverse eval :: representation -> meaning reify :: meaning -> representation Since several program representations can have the same meaning, the inverse is not usually a function, but a relation, so Haskell picks a partial implementation of 'reify', named 'show', applicable only to things that have a uniquely determined representation. And since Haskell implementations can't display things by themselves, they use 'show' to show at least some things. Now for the tricky part: as we write down or implement a semantics, we're using a secondary level of representation, so we have representations of program representations and representations of program meanings (we might say that the 'semantics of 3', '[| 3 |]', is the number '3'). In other words, we have a representation of 'eval' that maps representations of representations to representations of meanings. So when we write down a program, it is a program to us, but just a string to be interpreted for the implementation. And the implementation can give back a representation of the meaning to us, without ever passing such representation to other parts of the program (no 'show' involved). Concretely, we type in '(\x->\y->x+2) 1', and the implementation gives back '\y->3' without having to support any kind of reification operation in the program itself - no problem with referential transparency there. Claus (*:-) ".. The name of the song is called `Haddocks' Eyes'" "Oh, that's the name of the song, is it?" Alice said, trying to feel interested. "No, you don't understand," the Knight said, looking a little vexed. "That's what the name is called. The name really is `The Aged Aged Man.'" "Then I ought to have said `That's what the song is called'?" Alice corrected herself. "No, you oughtn't: that's quite another thing! The song is called `Ways And Means': but that is only what it's called, you know!" "Well, what is the song, then?" said Alice, who was by this time completely bewildered. "I was coming to that," the Knight said. "The song really is `A-sitting On A Gate'.." (Lewis Caroll, Through The Looking-Glass)
As far as referential transparency is concerned, you'd need to keep your reference levels straight, which can seem confusing if you can only communicate via representations(*:-)
That came out more confusing than it needs to be, so let me try that again, from scratch: Reduction systems take programs that are representations of problems and produce programs that are representations of solutions. One level of representation, so users can pretend there is no representation: for them, reduction systems reduce programs to simpler programs.
From the implementation perspective, representations of programs are translated downwards into executable code, the code is executed, the system states resulting at the end (or when the reduction count runs out) are translated upwards into representations of programs again.
Slightly more intricate, but users still see only programs reducing to other programs. It doesn't matter whether the end programs are values, functions, or partially reduced applications - they are always represented in the same high-level form users started out with, without user programs having to deal explicitly in representations. Referential transparency is never in question. In current Haskell implementations, representations of programs are translated downwards into executable code, the code is executed. There is something missing here: the resulting system states are never translated back into language-level representations, so users have to deal with the gap between high-level and low-level representations. To do that, we use 'show' and 'IO' in our programs - we write programs that talk about representations of a subset of programs, namely 'Show'able values, and about printing those representations. So we end up with representations of programs-that-print-out- representations-of-values; the programs are translated downwards into executable code, the code is executed, doing so prints out representations of values. What GHCi and Hugs do is to wrap a 'putStrLn . show' around our input programs, so there is some chance of getting a representation of result values back. GHCi also allows us to make and inspect (show values or types of) bindings at the prompt, but it doesn't give us a representation of the program context we are constructing. When using a reduction system, I was able to focus on programs. When using a Haskell implementation, I have to think about representations of results, and how I get them out of a running program. If the intended result is something for which programs cannot produce or print a representation (functions, partially reduced applications) I am stuck. I might ask for a debugger, if only to get some kinds of insight into what my program is doing when it isn't printing representations of values for me, but I won't get a language-level view of program execution via representations of intermediate programs. Hope that is a less confusing view of the differences, Claus
participants (7)
-
Achim Schneider -
Claus Reinke -
Dan Weston -
Heinrich Apfelmus -
Luke Palmer -
michael rice -
Miguel Mitrofanov