Re: [Haskell-cafe] cabal configure cabal build cabal install
On Mon, Nov 26, 2012 at 06:21:33PM -0500, Albert Y. C. Lai wrote: cabal configure is used by a lot of programmers. Today. Why? Because they use it on their own projects. They use cabal-install as a builder, not exactly an installer. Don't most devs nowadays use sandboxing, a.k.a. cabal-dev? I know I do, I've found cabal to be impossible to work with as a development tool without sandboxing. I think there was effort to bring cabal-dev like functionality to standard cabal in the next big release. Ah yes, here: http://hackage.haskell.org/trac/hackage/wiki/SandboxedBuildsAndIsolatedEnvironments In general, I consider sandboxing really important, even without dependency hell: I will sometimes want experimental and/or old versions of libraries to depend on that I don't want installed globally. Best, Aleks signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Observer pattern in haskell FRP
On 12/08/2012 10:32 AM, Heinrich Apfelmus wrote: Nathan Hüsken wrote: Heinrich Apfelmus wrote: In that light, the separation seems straightforward to me. Given the time-varying values that represent game objects, bSpaceShipPosition :: Behavior Position bAsteroidPositions :: Behavior [Position] bTime :: Behavior Time you can transform and combine them into a graphic, for instance like this bSpaceShipPicture :: Behavior Graphic bSpaceShipPicture = blinkenLights $ bTime * bSpaceShipPosition bAsteroidPictures = map drawAsteroid $ bAsteroidPositions bPicture = overlay $ ((:) $ bSpaceShipPicture * bAsteroidPictures) In other words, you just combine old time-varying values into new ones, much like you would combine combine graphical plots. Also note that you can add animation a posteriori; it doesn't have to be part of the values representing a space ship. Yes, but these examples are extremely simple. The animation has no internal state. What if every Asteroid also has a animation state (which I would want to add a posteriori) and can be destroyed. Than the connection between the asteroids game logic value, and rendering value needs some kind of bookkeeping to be maintained. Fair enough, but I don't see how this can be fitted into a general pattern. If the animation state is coupled tightly to the game logic state, then the question whether the animation is part of the game logic or not does not have a clear answer anymore. Hm. I see it like this: The logic state may not depend on the rendering state. If for example the animation of an asteroid changes how or when objects collide with it, than the animation is part of the logic. If however the physics of the game treat the asteroid as a object whose shape does not change depending in the animation, than the animation is part of the rendering state. So the coupling may only be logic-rendering. You mentioned that in an imperative setting, you would use something similar to the observer pattern. Judging from the wikipedia page http://en.wikipedia.org/wiki/Observer_pattern, it seems to me that this is just the Event type, though, so I don't understand how this helps with the problem at hand. Yes, you are right. The problem at hand is something one has to deal with when using the observer pattern. Only in C++ I do not find it hard to do. Maybe discussing a concrete example could be very helpful. Could you give a minimal example that still contains the key difficulties? Maybe a collection of asteroids that float in space, can be added or removed with a button click and who are animated as rotating rocks, all starting in a certain position when they are created? How would you use the observer pattern in this case? I put a pseudo C++ example below the mail. I use the terms model and view for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over. As you said, this basically is sending messages from the Model (in the observer pattern called Observable) to the view (Observer). The main difficulty I have is how to send the messages from the correct model to the correct view. In C++ this is done by keeping pointers. Simply assigning IDs would work, but than I would have to always pass a map from the model to the view, and I feel like (also I have little experience with this), that this approach is not very scalable. Best Regards, Nathan === The C++ example, its not complete, but I believe it captures the idea. class GalaxyModel { GalaxyView* view; listAsteroidModel asteroids; void addAsteroid(Position pos) { asteroids.push(AsteroidModel(pos)); view-onNewAsteroid(asteroids.back()); } void update() { for (a in asteroids) { a.update(); } for(a in asteroids) { for (b in asteroids) { if (collide(a,b)) { a.explode(); b.explode(); asteroids.remove(a); asteroids.remove(b); } } } } }; class AsteroidModel { AsteroidView* view; Position pos; update() { updatePosition(); view-onNewPos(pos); } explode() { view-onExplode(); } }; class GalaxyView { listAstroidView asteroids; void onNewAsteroid(AsteroidModel* model) { asteroids.push(AsteroidView(model)); } void update() { for (a in asteroids) { a.update(); if (a.dead) asteroids.remove(a); } } } class AsteroidView { float rotation; bool dead = false; void onExplode() { setExplodeAnimation(); } void onNewPos() { //Store position} void update() { rotation += 1.0; if (explodeAnimationOver()) { m_dead = true; } } } ___ Haskell-Cafe mailing list
Re: [Haskell-cafe] Observer pattern in haskell FRP
Nathan Hüsken nathan.hues...@posteo.de wrote: I put a pseudo C++ example below the mail. I use the terms model and view for the game logic and rendering respectively. The example is a little different. Asteroids explode when they collide. The moment asteroids explode, they are removed from the model (the game logic) while in the view (rendering) they still exist until the explosion animation is over. As you said, this basically is sending messages from the Model (in the observer pattern called Observable) to the view (Observer). The main difficulty I have is how to send the messages from the correct model to the correct view. In C++ this is done by keeping pointers. Simply assigning IDs would work, but than I would have to always pass a map from the model to the view, and I feel like (also I have little experience with this), that this approach is not very scalable. Actually it is very scalable, as the same map is passed to every object. It can even live in the underlying monad, which means that you could even use a mutable vector, if you wish; however, I don't recommend that. Remember that a map is immutable and shared, so passing the same map to multiple objects is in fact the same as passing a pointer in C++. Lookups in and updates to the map are of logarithmic complexity, so this scales well. Only doubling the number of nodes actually adds one full step to lookups and updates. If you're dealing with millions of objects you may want to use the vector solution mentioned earlier. This requires an imperative underlying monad, but you would get about the same speed as in C++. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad. signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] mtl: Why there is Monoid w constraint in the definition of class MonadWriter?
I guess you have a point here: 1. The definition of the MonadWriter operations does not need the Monoid operations. Hence, the class constraint Monoid w should be removed. 2. The formulation of the MonadWriter laws (which are sadly missing from the documentation) would need the Monoid operations, though, e.g. tell v tell w = tell (v w) This is a weak indication that a constraint Monoid w should be present. However, currently Haskell does not provide a formal specification of laws (except maybe as RULES!?), so having the constraint here is a bit too eager. The story would be different in Agda... Indeed, if one wants Roman's MyWriter to be an instance of MonadWriter, one needs to declare an annoying fake monoid instance for Integer. {-# LANGUAGE MultiParamTypeClasses, DeriveFunctor, GeneralizedNewtypeDeriving #-} import Control.Arrow import Control.Applicative import Control.Monad.Writer import Data.Monoid newtype MyWriter a = MyWriter { myWriter :: Writer (Sum Integer) a } deriving (Functor, Monad) instance Monoid Integer where instance MonadWriter Integer MyWriter where tell w = MyWriter $ tell $ Sum w listen m = MyWriter $ (id *** getSum) $ listen (myWriter m) pass m = MyWriter $ pass $ (id *** \ f - Sum . f . getSum) $ myWriter m Petr, you might wanna make a propsal to remove the Monoid w constraint to librar...@haskell.org, summarizing the current state of discussion so far. Cheers, Andreas On 09.12.2012 11:04, Petr P wrote: Hi all, I'd say that a type class declares functions and specifies laws (in the docs) what its implementations must adhere to. It's not the job of a type class to fulfill the laws, it's the job of its implementations. So the reason for 'Monoid w' in 'MonadWriter' cannot be that then 'MonadWriter' wouldn't be a monad. Such constraints should be required only by implementations. It is true that any Writer has an implicit underlying monoid, and we can even extract the operations from it as follows. The empty element can be extracted as empty = liftM snd (listen (return ())) :: m w Having this 'empty', we can give 'const empty' to 'pass' to discard output of an action, so we can construct: -- | @contained m@ executes the action @m@ in a contained environment and -- returns its value and its output. The current output is not modified. contained :: m a - m (a, w) contained k = do -- we can retrieve mempty even if we don't have the monoid constraint: ~(_, empty) - listen (return ()) This seems a contrived way of getting 'empty'. In this case, I prefer the monoid instance. -- listen what @k@ does, get its result and ignore its output change: pass (listen k = \x - return (x, const empty)) This generalizes 'listen' and 'pass' (both can be easily defined from it) and I find this function much easier to understand. In a way, it is also a generalization of WriterT's runWriterT, because for WriterT we have 'contained = lift . runWriterT'. [I implemented 'contained' in a fork of the mtl library, if anybody is interested: https://github.com/ppetr/mtl ] With that, we can do -- Doesn't produce any output, only returns the combination -- of the arguments. append x y = liftM snd $ contained (tell x tell y) :: w - w - m w I didn't check the monoid laws, but it seems obvious that they follow from the monad laws and (a bit vague) specification of 'listen' and 'pass'. Personally, I'd find it better if `MonadWriter` would be split into two levels: One with just 'tell' and 'writer' and the next level extending it with 'listen'/'pass'/'contained'. The first level would allow things like logging to a file, without any monoidal structure. But this would break a lot of stuff (until we agree on and develop something like http://hackage.haskell.org/trac/ghc/wiki/DefaultSuperclassInstances). Best regards, Petr 2012/12/9 Roman Cheplyaka r...@ro-che.info mailto:r...@ro-che.info * Edward Z. Yang ezy...@mit.edu mailto:ezy...@mit.edu [2012-12-08 15:45:54-0800] Second, even *if* the above holds (two tells are equivalent to one tell), then there is *some* function f such that tell w1 tell w2 == tell (f w1 w2) It isn't necessary that f coincides with mappend, or even that the type w is declared as a Monoid at all. The only thing we can tell from the Monad laws is that that function f should be associative. Well, the function is associative: that's half of the way there to a monoid; all you need is the identity! But we have those too: whatever the value of the execWriter (return ()) is... Let me repeat: It isn't necessary that f coincides with mappend, or even that the type w is declared as a Monoid at all. Let me illustrate this with an example. data MyWriter a = MyWriter Integer a instance Monad MyWriter where
[Haskell-cafe] ANNOUNCE: tie-knot library
Dear Haskellers, I'd like to announce a small library tie-knot: Ties the knot on a given set of structures that reference each other by keys - replaces the keys with their respective values. Takes Map k (v k) and converts into Map k v' where v' is the fixed point of v. Motivation: I needed to assemble a finite-state machine from an external description where each node was described by some identifier. I needed a simple library that would replace all key referencess with the actual values. See https://github.com/ppetr/tie-knot for examples. Hackage: http://hackage.haskell.org/package/tie-knot - Petr Pudlak ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] mtl: Why there is Monoid w constraint in the definition of class MonadWriter?
Hi Petr, On Sun, Dec 9, 2012 at 7:59 AM, Petr P petr@gmail.com wrote: The class is defined as class (Monoid w, Monad m) = MonadWriter w m | m - w where ... What is the reason for the Monoid constrait? It seems superfluous to me. I recompiled the whole package without it, with no problems. How I see it, the MTL classes are there to lift operations automatically through layers of transformers. They're just a hack to avoid having to call `lift` all the time, and aren't really designed to be used on monads other than the original WriterT. With this interpretation, the constraint makes sense -- it is simply reflecting the constraints already on the concrete monad. Chris Of course, the Monoid constraint is necessary for most _instances_, like in instance (Monoid w, Monad m) = MonadWriter w (Lazy.WriterT w m) where ... but this is a different thing - it depends on how the particular instance is implemented. I encountered the problem when I needed to define an instance where the monoidal structure is fixed (Last) and I didn't want to expose it to the user. I wanted to spare the user of of having to write Last/getLast everywhere. (I have an instance of MonadWriter independent of WriterT, its 'tell' saves values to a MVar. Functions 'listen' and 'pass' create a new temporary MVar. I can post the detail, if anybody is interested.) Would anything break by removing the constraint? I think the type class would get a bit more general this way. Thanks for help, Petr Pudlak ___ 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
Re: [Haskell-cafe] Variable-arity zipWith (re)invented.
On Sat, Dec 8, 2012 at 10:27 AM, Takayuki Muranushi muranu...@gmail.com wrote: Continued discussion from https://groups.google.com/d/topic/haskell-cafe/-e-xaCEbd-w/discussion https://groups.google.com/d/topic/haskell-cafe/kM_-NvXAcx8/discussion Thank you for all the answeres and thinkings; Here's zipWithN for general Zip functors: [1] . This, together with [2] may constitute a small hackage. A modification from Wren's idea to [1] is the use of fmap instead of repeat. I'm wondering if there are any laws for Zip functors. I first thought that there are similarity between Zips and Applicatives, as [3] states instance Applicative f = Zip f where zip = liftA2 (,) However, my intuition is that zipping two arrays should result in an array of size of the same order as two, giving rise to a Zip functor law candidate: zipWith const xs $ zipWith const xs ys == zipWith const xs ys which is violated by the above statement zip = liftA2 (,) . [1] https://github.com/nushio3/practice/blob/master/variable-arity/ZipWithN-2.hs [2] https://github.com/nushio3/practice/blob/master/free-objects/zipf-12.hs [3] http://hackage.haskell.org/packages/archive/TypeCompose/0.9.7/doc/html/Data-Zip.html Hi again, Takayuki While the forZN in zipf-12 is able to infer the result type given arguments, it doesn't give any useful information about types for arguments unlike an example here: http://code.haskell.org/~aavogt/flip_zipWithN/P4.hs which imports a slight modification of Paczesiowa's code: http://code.haskell.org/~aavogt/flip_zipWithN/Part1.lhs But maybe it isn't possible to infer much about earlier arguments given later ones since there is an instance Zip ((-) a), that forZN apparently can work with. Adam ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Variable-arity zipWith (re)invented.
Repeated thanks to you, Adam! Your code is brilliantly simple. Sadly, I cannot reproduce the behaviors in your comments on my ghci (7.6.1) . Can we guess why? The version of packages we are using? Mines are here. https://github.com/nushio3/practice/tree/master/variable-arity/adam :t forZ [1,2,3] (+) forZ [1,2,3] (+) :: (Num t, Num a, TypeCast br HFalse, HBuild2' br (HCons [t] HNil) (a - a - a) r) = r forZ [1,2,3] [10] (+) interactive:13:1: Couldn't match type `[y]' with `(a0 - a0 - a0) - t0' When using functional dependencies to combine Apply ApplyZap (a, b) [y], arising from the dependency `f a - r' in the instance declaration at Part1.lhs:193:12 Apply ApplyZap ([[t2]], [t1]) ((a0 - a0 - a0) - t0), arising from a use of `forZ' at interactive:13:1-4 In the expression: forZ [1, 2, 3] [10] (+) In an equation for `it': it = forZ [1, 2, 3] [10] (+) forZ [1,2,3] hi there (,) interactive:14:1: Couldn't match type `[y]' with `(a0 - b0 - (a0, b0)) - t0' When using functional dependencies to combine Apply ApplyZap (a, b) [y], arising from the dependency `f a - r' in the instance declaration at Part1.lhs:193:12 Apply ApplyZap ([[Char]], [t1]) ((a0 - b0 - (a0, b0)) - t0), arising from a use of `forZ' at interactive:14:1-4 In the expression: forZ [1, 2, 3] hi there (,) In an equation for `it': it = forZ [1, 2, 3] hi there (,) Best, Takayuki 2012/12/11 adam vogt vogt.a...@gmail.com: On Sat, Dec 8, 2012 at 10:27 AM, Takayuki Muranushi muranu...@gmail.com wrote: Continued discussion from https://groups.google.com/d/topic/haskell-cafe/-e-xaCEbd-w/discussion https://groups.google.com/d/topic/haskell-cafe/kM_-NvXAcx8/discussion Thank you for all the answeres and thinkings; Here's zipWithN for general Zip functors: [1] . This, together with [2] may constitute a small hackage. A modification from Wren's idea to [1] is the use of fmap instead of repeat. I'm wondering if there are any laws for Zip functors. I first thought that there are similarity between Zips and Applicatives, as [3] states instance Applicative f = Zip f where zip = liftA2 (,) However, my intuition is that zipping two arrays should result in an array of size of the same order as two, giving rise to a Zip functor law candidate: zipWith const xs $ zipWith const xs ys == zipWith const xs ys which is violated by the above statement zip = liftA2 (,) . [1] https://github.com/nushio3/practice/blob/master/variable-arity/ZipWithN-2.hs [2] https://github.com/nushio3/practice/blob/master/free-objects/zipf-12.hs [3] http://hackage.haskell.org/packages/archive/TypeCompose/0.9.7/doc/html/Data-Zip.html Hi again, Takayuki While the forZN in zipf-12 is able to infer the result type given arguments, it doesn't give any useful information about types for arguments unlike an example here: http://code.haskell.org/~aavogt/flip_zipWithN/P4.hs which imports a slight modification of Paczesiowa's code: http://code.haskell.org/~aavogt/flip_zipWithN/Part1.lhs But maybe it isn't possible to infer much about earlier arguments given later ones since there is an instance Zip ((-) a), that forZN apparently can work with. Adam -- Takayuki MURANUSHI The Hakubi Center for Advanced Research, Kyoto University http://www.hakubi.kyoto-u.ac.jp/02_mem/h22/muranushi.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe