Hello Peter, Thursday, April 16, 2009, 12:29:41 PM, you wrote:
Lennart (and Patai) said about unsafePerformIO, you - about NOINLINE > Well, the documentation says: > Use {-# NOINLINE foo #-} as a pragma on any function foo that calls > unsafePerformIO. If the call is inlined, the I/O may be performed more than > once. > > So you claim this does not prevent GHC to inline it anyway? That > feels like a bug then, both in the documentation and NOINLINE > On Thu, Apr 16, 2009 at 10:18 AM, Lennart Augustsson <lenn...@augustsson.net> > wrote: > > There's no guarantee about unsafePerformIO not being inlined, that's > just how ghc treats it. > > 2009/4/16 Patai Gergely <patai_gerg...@fastmail.fm>: > >>> On the other hand, breaking referential transparency in the >>> external interface is a very bad idea, in my opinion. Actually, >>> this means that the library user would have to turn certain >>> compiler optimizations off to get the intended behavior. >> However, in practice you can compile Elerea with -O2 without ill >> effects. In fact, that's what happens if you install it with cabal. >> >>> Just have a look at the Haddock docs of unsafePerformIO. >> Yes, I did that too, and came up with the following checklist: >> >> - the order of side effects doesn't matter much, since the resulting >> networks are equivalent if we don't rely on the automatic delay feature >> (applicative optimisations can be different, but still with the same net >> effect) >> - unsafePerformIO is apparently never inlined, i.e. each instance is >> executed once, so sharing works as desired >> - let-floating is no problem, because all instances of unsafePerformIO >> rely on surrounding function arguments >> - CSE is no problem either, it even helps if it's performed (and it is >> with optimisations turned on), since it results in smaller equivalent >> networks >> >> I think we can expect it to be fairly well-behaving, because the 'side >> effect' of Elerea primitives is basically the same as that of pure >> values in general: upon evaluation a value is created in the memory and >> we get a reference to it. We only have an extra constraint for the >> compiler: never duplicate these values. Merging identical ones is okay, >> and in fact desirable. The following code demonstrates this if you >> compile it with and without optimisations: >> >> import Control.Applicative >> import Control.Monad >> import FRP.Elerea >> import System.IO.Unsafe >> >> cint a b = unsafePerformIO (putStrLn "!") `seq` >> transfer 0 (\dt x x0 -> x0+x*dt) b >> >> mysig = (latcher 0 (b >@ 0.3) (const (cint a b) <$> cint a b)) + >> (cint a b) + (cint a b) + a >> where a = pure 4 >> b = stateful 0 (+) >> >> main = replicateM 10 (superstep mysig 0.1) >>= print >> >> I'd like to see an example where optimisation does make a difference, >> because I'm still unsure about the consequences of 'unsafeness'. >> >> Gergely >> >> -- >> http://www.fastmail.fm - Or how I learned to stop worrying and >> love email again >> >> _______________________________________________ >> Haskell-Cafe mailing list >> Haskell-Cafe@haskell.org >> http://www.haskell.org/mailman/listinfo/haskell-cafe >> > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > -- Best regards, Bulat mailto:bulat.zigans...@gmail.com _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe