From c at chrisbolton.me Fri Nov 1 20:27:02 2013 From: c at chrisbolton.me (Chris Bolton) Date: Fri, 1 Nov 2013 13:27:02 -0700 Subject: [Haskell-beginners] code review Message-ID: Just finished my first haskell library this morning and thought I'd throw it up on the mailing list and see if anyone had any suggestions. Still pretty new to haskell and I?m sure it?s not super idiomatic. https://github.com/saiko-chriskun/migrate https://github.com/saiko-chriskun/migrate-rethinkdb -------------- next part -------------- An HTML attachment was scrubbed... URL: From hjgtuyl at chello.nl Fri Nov 1 21:39:41 2013 From: hjgtuyl at chello.nl (Henk-Jan van Tuyl) Date: Fri, 01 Nov 2013 22:39:41 +0100 Subject: [Haskell-beginners] code review In-Reply-To: References: Message-ID: On Fri, 01 Nov 2013 21:27:02 +0100, Chris Bolton wrote: > Just finished my first Haskell library this morning and thought I'd > throw it up on the mailing list and see if anyone had any suggestions. > Still pretty new to Haskell and I?m sure it?s not super idiomatic. > > https://github.com/saiko-chriskun/migrate > https://github.com/saiko-chriskun/migrate-rethinkdb As a Windows user, I am not very fond of getUnixTime; can't you use getCurrentTime from Data.Time.Clock? This is from package time, which is included in the Haskell Platform. Regards, Henk-Jan van Tuyl -- Folding at home What if you could share your unused computer power to help find a cure? In just 5 minutes you can join the world's biggest networked computer and get us closer sooner. Watch the video. http://folding.stanford.edu/ http://Van.Tuyl.eu/ http://members.chello.nl/hjgtuyl/tourdemonad.html Haskell programming -- From franco00 at gmx.com Tue Nov 5 13:33:29 2013 From: franco00 at gmx.com (Franco) Date: Tue, 5 Nov 2013 14:33:29 +0100 Subject: [Haskell-beginners] heterogeneous containers and static typing Message-ID: <20131105133329.GA3489@efikamx> Hello, I am developing a small game engine (nothing fancy or professional, it is to test the waters of Haskell). You could say it's a very simple DSL: a user would import a library and use its tool to make a game. The problem I encountered is when defining or getting/setting variables for an instance game. Let me illustrate data GameState = GameState [(String, Int)] This is a very simple and naive gamestate, an association list consisting in (variableName, itsValue). This would mean restricting values to "Int" only, but I can easily enough add any kind of value with: data GameState = GameState [(String, Dynamic)] An example helper function signature would look like getBool :: String -> Either MyError Bool data MyError = NotFound String | TypeMismatch String The problem with this approach is that I loathe picking up those two kind of errors (var not found and type mismatch) at runtime. I would like them to be found at compile time (like "normal" Haskell). I thought that a possible solution was to declare a datatype with the needed variables inside: data MyGameVar = MyGameVar { health :: Int, message :: String } myvars = MyGameVar 1 "Don't forget your umbrella!" This would find at compile time typos in variable names and type errors at compile time, of course. But then I would have to change the GameState to: data GameState = GameState MyGameVar which would be fine if I were developing a *game*, but it is not fine when you develop a *game engine* (that would mean having to rewrite MyGameVar every game you made). So I am left to think if the problem I highlighted is "solvable" or do I have to make compromises? I guess I am not the first to encounter this difficulty, so I am asking here. Any hint or idea is appreciated, thanks! -F From ryan.trinkle at gmail.com Tue Nov 5 15:11:08 2013 From: ryan.trinkle at gmail.com (Ryan Trinkle) Date: Tue, 5 Nov 2013 10:11:08 -0500 Subject: [Haskell-beginners] heterogeneous containers and static typing In-Reply-To: <20131105133329.GA3489@efikamx> References: <20131105133329.GA3489@efikamx> Message-ID: Hi Franco, Have you considered allowing the user of your game engine to supply his or her own type for the game state? You could combine this with any state that the engine itself needs, like so: data GameState a = GameState EngineState a Then, your user could make use of 'GameState MyGameState' to hold both his or her own game's state as well as the engine's state. Ryan On Tue, Nov 5, 2013 at 8:33 AM, Franco wrote: > Hello, > > I am developing a small game engine (nothing fancy or professional, it > is > to test the waters of Haskell). You could say it's a very simple DSL: a > user would import a library and use its tool to make a game. > > The problem I encountered is when defining or getting/setting variables > for an > instance game. Let me illustrate > > data GameState = GameState [(String, Int)] > > This is a very simple and naive gamestate, an association list consisting > in (variableName, itsValue). This would mean restricting values to "Int" > only, > but I can easily enough add any kind of value with: > > data GameState = GameState [(String, Dynamic)] > > An example helper function signature would look like > > getBool :: String -> Either MyError Bool > data MyError = NotFound String > | TypeMismatch String > > The problem with this approach is that I loathe picking up those two kind > of > errors (var not found and type mismatch) at runtime. I would like them to > be > found at compile time (like "normal" Haskell). > > I thought that a possible solution was to declare a datatype with the > needed > variables inside: > > data MyGameVar = MyGameVar { health :: Int, > message :: String } > myvars = MyGameVar 1 "Don't forget your umbrella!" > > This would find at compile time typos in variable names and type errors at > compile time, of course. But then I would have to change the GameState to: > > data GameState = GameState MyGameVar > > which would be fine if I were developing a *game*, but it is not fine when > you develop a *game engine* (that would mean having to rewrite MyGameVar > every game you made). > > So I am left to think if the problem I highlighted is "solvable" or do I > have to make compromises? I guess I am not the first to encounter this > difficulty, so I am asking here. > Any hint or idea is appreciated, thanks! > -F > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From poczta at emanuelkoczwara.pl Thu Nov 7 09:26:10 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Thu, 07 Nov 2013 10:26:10 +0100 Subject: [Haskell-beginners] xmpp server Message-ID: <527B5CB2.1090302@emanuelkoczwara.pl> Hi, I want to write xmpp server to learn how to do networking, threading, xml, config files and logging. Time to write a real app. Anybody wants to help? Emanuel From artur.tadrala at gmail.com Thu Nov 7 09:42:35 2013 From: artur.tadrala at gmail.com (=?ISO-8859-2?Q?Artur_Tadra=B3a?=) Date: Thu, 7 Nov 2013 09:42:35 +0000 Subject: [Haskell-beginners] xmpp server In-Reply-To: <527B5CB2.1090302@emanuelkoczwara.pl> References: <527B5CB2.1090302@emanuelkoczwara.pl> Message-ID: Hi, I'd like to join you on that one, but don't know if I can help you much. I'm beginner. I have a few years in OOP. Just drop me an email, unless you search for experienced haskeller for guidance. Artur 2013/11/7 Emanuel Koczwara > Hi, > > I want to write xmpp server to learn how to do networking, threading, > xml, config files and logging. Time to write a real app. Anybody wants to > help? > > Emanuel > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From poczta at emanuelkoczwara.pl Thu Nov 7 09:53:20 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Thu, 07 Nov 2013 10:53:20 +0100 Subject: [Haskell-beginners] xmpp server In-Reply-To: References: <527B5CB2.1090302@emanuelkoczwara.pl> Message-ID: <527B6310.6040702@emanuelkoczwara.pl> Hi, W dniu 07.11.2013 10:42, Artur Tadra?a pisze: > Hi, > > I'd like to join you on that one, but don't know if I can help you > much. I'm beginner. I have a few years in OOP. Just drop me an email, > unless you search for experienced haskeller for guidance. > > Artur > I'm beginner also. This would be an educational project. Emanuel From michael at snoyman.com Thu Nov 7 09:56:39 2013 From: michael at snoyman.com (Michael Snoyman) Date: Thu, 7 Nov 2013 11:56:39 +0200 Subject: [Haskell-beginners] xmpp server In-Reply-To: <527B6310.6040702@emanuelkoczwara.pl> References: <527B5CB2.1090302@emanuelkoczwara.pl> <527B6310.6040702@emanuelkoczwara.pl> Message-ID: On Thu, Nov 7, 2013 at 11:53 AM, Emanuel Koczwara wrote: > Hi, > > W dniu 07.11.2013 10:42, Artur Tadra?a pisze: > > Hi, >> >> I'd like to join you on that one, but don't know if I can help you much. >> I'm beginner. I have a few years in OOP. Just drop me an email, unless you >> search for experienced haskeller for guidance. >> >> Artur >> >> > I'm beginner also. This would be an educational project. > > > Emanuel > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > I know there's been a lot of effort put into the pontarius-xmpp library[1]. Marcos Pividori used it to implement parts of his GSoC project[2], which I mentored. [1] http://hackage.haskell.org/package/pontarius-xmpp [2] http://hackage.haskell.org/package/push-notify-ccs -------------- next part -------------- An HTML attachment was scrubbed... URL: From thbach at students.uni-mainz.de Thu Nov 7 15:40:47 2013 From: thbach at students.uni-mainz.de (Thomas Bach) Date: Thu, 7 Nov 2013 16:40:47 +0100 Subject: [Haskell-beginners] IPerf in Haskell doesn't perform Message-ID: <527BB47F.40406@students.uni-mainz.de> Hi list, I had to do a little benchmarking of a network connection between two servers and I thought ?Well, Haskell seemed pretty awesome, let's use it to accomplish the task.? So I spent a couple of days with the Haskell library and finally got the following (working!) code (see below). Now my questions: 1) Although being a beautiful language, my code seems to be ugly. Any hints to improve this? My problem is (I think) that I simply cannot get rid of the IO Monad and the only way I know how to deal with this is by using lots of 'do's which doesn't help at all to get rid of the monads. (Probably the imperative background problem?) :) 2) The program I wrote doesn't perform. It sended around 33 MBytes in 10 seconds over a connection where iperf (the one packaged by Ubuntu, written in C) was able send 650 MBytes. Where can I improve performance? I'm especially interested in the low hanging fruits, which are easy to understand as a Haskell novice. ;) 3) When I run this program, I get the following Error (both, on the client, as well as on the server): $./iperf -c localhost "Running as client connecting to localhost" Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize -RTS' to increase it. enlarging the stack space avoids it, but how can I avoid it in the code? I guess that the stack space overflow comes from the recursive call to receiveData on the server and sendIntermediateAndFinalData in the client. I thought that in the way I implemented it, these functions are tailor recursive and therefor not prone to stack overflows!?! Anyway, I didn't check that, so maybe the error is somewhere else? Regards, Thomas Bach. PS: This is the code pasted ?As Quotation?. I couldn't find another way to get the code into Thunderbird w/o messing up line breaks and the like. I additionally added the code as an attachment. I hope this is ok ? time to get a new MUA! > import Data.Time (DiffTime, utctDayTime, getCurrentTime) > import Foreign (ForeignPtr, Int64, Ptr, mallocForeignPtr, withForeignPtr) > import Foreign.Storable (sizeOf, peek, poke) > import GHC.IO.Handle (Handle, BufferMode(NoBuffering), hClose, hGetBuf, hSetBuffering, hPutBuf) > import Network (Socket, HostName, PortID(PortNumber), PortNumber, accept, connectTo, listenOn, withSocketsDo) > import System.Console.GetOpt (ArgOrder(Permute), ArgDescr(..), OptDescr(..), getOpt, usageInfo) > import System.Environment (getArgs) > > data Flag = Client String | Server > deriving Show > > -- Command line arguments for server and client mode. > > options :: [OptDescr Flag] > options = > [ Option ['c'] ["client"] (ReqArg Client "HOST") "Connect to host as client." > , Option ['s'] ["server"] (NoArg Server) "Run as server." > ] > > perfOpts :: [String] -> IO [Flag] > perfOpts argv = > case getOpt Permute options argv of > ([], [], []) -> ioError (userError ("At least one Option is needed." ++ usageInfo "" options)) > (o, [], []) -> return o > (_, _, errs) -> ioError (userError (concat errs ++ usageInfo "" options)) > > -- Some constants > > port = PortNumber 8456 > type Trans = Int64 > numBytes = sizeOf (0 :: Trans) > inital = -128 :: Trans > intermediate = 0 :: Trans > final = 127 :: Trans > > makePtr = mallocForeignPtr :: IO (ForeignPtr Trans) > > -- The client connects to the server, initializes the connection > -- by sending initial, sends then for the amount of at least > -- 10 secs as much intermediate (0's) as possible and finally > -- sends final. > > runClient :: String -> IO () > runClient host = do > print ("Running as client connecting to " ++ host) > hdl <- initClient host port > ptr <- makePtr > fillInitial ptr > withForeignPtr ptr (sendBuf hdl) > fillIntermediate ptr > curTime <- fmap utctDayTime getCurrentTime > (sentBytes, time) <- sendIntermediateAndFinal ptr hdl curTime 10 0 > print ("Sent " ++ show sentBytes ++ " Bytes in " ++ show time ++ " seconds.") > hClose hdl > > initClient :: HostName -> PortID -> IO Handle > initClient host port = withSocketsDo $ do > hdl <- connectTo host port > hSetBuffering hdl NoBuffering > return hdl > > sendIntermediateAndFinal :: ForeignPtr Trans -> Handle -> DiffTime -> DiffTime -> Int -> IO (Int, DiffTime) > sendIntermediateAndFinal ptr hdl start duration sent = do > curTime <- fmap utctDayTime getCurrentTime > if (curTime - start) > duration > then do fillFinal ptr > withForeignPtr ptr (sendBuf hdl) > finishedTime <- fmap utctDayTime getCurrentTime > return (sent + numBytes, finishedTime - start) > else do withForeignPtr ptr (sendBuf hdl) > sendIntermediateAndFinal ptr hdl start duration (sent + numBytes) > > sendBuf :: Handle -> Ptr Trans -> IO () > sendBuf hdl buf = hPutBuf hdl buf numBytes > > fillPtr :: Trans -> ForeignPtr Trans -> IO () > fillPtr num ptr = withForeignPtr ptr (\p -> poke p num) > > fillInitial = fillPtr inital > fillIntermediate = fillPtr intermediate > fillFinal = fillPtr final > > -- The server simply accepts connections, receives what it can get > -- and adds up the received bytes and transmission time. > > runServer :: IO () > runServer = do > print "Running as server." > initServer port >>= handleConnection > > initServer :: PortID -> IO Socket > initServer port = withSocketsDo $ listenOn port > > handleConnection :: Socket -> IO () > handleConnection socket = do > (hdl, host, port) <- acceptConnection socket > print ("Connection from " ++ host) > ptr <- makePtr > (num, bytes) <- receive ptr hdl > curTime <- fmap utctDayTime getCurrentTime > if num == inital > then do (received, time) <- receiveData ptr hdl curTime 0 > print ("Received " ++ show received ++ " in " ++ show time ++ " seconds.") > hClose hdl > handleConnection socket > else do print ("ERR: Expected " ++ show inital ++ " got " ++ show num) > hClose hdl > handleConnection socket > > acceptConnection :: Socket -> IO (Handle, HostName, PortNumber) > acceptConnection socket = do > (hdl, host, port) <- accept socket > hSetBuffering hdl NoBuffering > return (hdl, host, port) > > receiveData :: ForeignPtr Trans -> Handle -> DiffTime -> Int -> IO (Int, DiffTime) > receiveData ptr hdl started received = do > (num, bytes) <- receive ptr hdl > if num /= final > then receiveData ptr hdl started (received + bytes) > else do curTime <- fmap utctDayTime getCurrentTime > return (received + bytes, curTime - started) > > receive :: ForeignPtr Trans -> Handle -> IO (Trans, Int) > receive ptr hdl = do > withForeignPtr ptr (\p -> hGetBuf hdl p numBytes) > num <- withForeignPtr ptr peek > return (num, numBytes) > > -- The main routine decides whether to run as server or client. > > main :: IO () > main = do > opts <- getArgs >>= perfOpts > if length opts /= 1 > then ioError (userError ("Too many arguments!" ++ usageInfo "" options)) > else > case head opts of > Server -> runServer > Client host -> runClient host -------------- next part -------------- A non-text attachment was scrubbed... Name: iperf.hs Type: text/x-haskell Size: 4927 bytes Desc: not available URL: From franco00 at gmx.com Thu Nov 7 16:02:38 2013 From: franco00 at gmx.com (Franco) Date: Thu, 7 Nov 2013 16:02:38 +0000 (UTC) Subject: [Haskell-beginners] heterogeneous containers and static typing References: <20131105133329.GA3489@efikamx> Message-ID: Ryan Trinkle gmail.com> writes: > > > Hi Franco, > Have you considered allowing the user of your game engine to supply his or her own type for the game state? ?You could combine this with any state that the engine itself needs, like so: > > data GameState a = GameState EngineState a > > Then, your user could make use of 'GameState MyGameState' to hold both his or her own game's state as well as the engine's state. > > A very elegant and simple solution, thank you! From bob at redivi.com Thu Nov 7 22:55:17 2013 From: bob at redivi.com (Bob Ippolito) Date: Thu, 7 Nov 2013 14:55:17 -0800 Subject: [Haskell-beginners] IPerf in Haskell doesn't perform In-Reply-To: <527BB47F.40406@students.uni-mainz.de> References: <527BB47F.40406@students.uni-mainz.de> Message-ID: I took your code and made a few style cleanups so that hlint wouldn't complain and so that it would be easier to read. Then I read through the code and found where your code had a space leak (repeated in the client and server code). I haven't put any effort into benchmarking, profiling, etc., just cleaning it up and fixing the algorithmic issues that I noticed. Here's the current version: https://gist.github.com/etrepum/7362646 You can see the revisions here: https://gist.github.com/etrepum/7362646/revisions The space leak is a strictness issue that is common for Haskell beginners to do. Before bothering to read any more of this message, I highly recommend reading this section of Parallel and Concurrent Programming in Haskell. It has great coverage on how Haskell's evaluation works: http://chimera.labs.oreilly.com/books/1230000000929/ch02.html#sec_par-eval-whnf Here's a minimal-ish example of what your code ends up doing: sum :: [Int] -> Int sum = sum' 0 sum' :: Int -> [Int] -> Int sum' acc (x:xs) = sum' (acc + x) xs sum' acc _ = acc Why does this code have a space leak? Because `acc` is never forced. When sum' recurses, the first argument is a thunk `x + acc` rather than the value of that computation. This is a space leak because the value of `x + acc` can be stored in constant space (an Int) but the nested thunks takes up linear space (a thunk that references `x` and `acc` which is a thunk itself except for the initial 0). The stack overflow happens because linear stack space and computation is required to evaluate this thunk, which your code does at the end when it prints the value. There are many ways to fix this, one way without resorting to BangPatterns would be to use `seq` to ensure that acc is evaluated before it is used. sum :: [Int] -> Int sum = sum' 0 sum' :: Int -> [Int] -> Int sum' acc _ | seq acc False = undefined sum' acc (x:xs) = sum' (acc + x) xs sum' acc _ = acc The BangPatterns method used in my cleanup is basically syntax sugar for the above, but it is not currently part of the Haskell standard so a LANGUAGE pragma is required to use it. -bob On Thu, Nov 7, 2013 at 7:40 AM, Thomas Bach wrote: > Hi list, > > I had to do a little benchmarking of a network connection between two > servers and I thought ?Well, Haskell seemed pretty awesome, let's use it > to accomplish the task.? So I spent a couple of days with the Haskell > library and finally got the following (working!) code (see below). Now > my questions: > > 1) Although being a beautiful language, my code seems to be ugly. Any > hints to improve this? My problem is (I think) that I simply cannot get > rid of the IO Monad and the only way I know how to deal with this is by > using lots of 'do's which doesn't help at all to get rid of the monads. > (Probably the imperative background problem?) :) > > 2) The program I wrote doesn't perform. It sended around 33 MBytes in 10 > seconds over a connection where iperf (the one packaged by Ubuntu, > written in C) was able send 650 MBytes. Where can I improve performance? > I'm especially interested in the low hanging fruits, which are easy to > understand as a Haskell novice. ;) > > 3) When I run this program, I get the following Error (both, on the > client, as well as on the server): > > $./iperf -c localhost > "Running as client connecting to localhost" > Stack space overflow: current size 8388608 bytes. > Use `+RTS -Ksize -RTS' to increase it. > > enlarging the stack space avoids it, but how can I avoid it in the code? > I guess that the stack space overflow comes from the recursive call to > receiveData on the server and sendIntermediateAndFinalData in the > client. I thought that in the way I implemented it, these functions are > tailor recursive and therefor not prone to stack overflows!?! Anyway, I > didn't check that, so maybe the error is somewhere else? > > Regards, > Thomas Bach. > > PS: This is the code pasted ?As Quotation?. I couldn't find another way > to get the code into Thunderbird w/o messing up line breaks and the > like. I additionally added the code as an attachment. I hope this is ok > ? time to get a new MUA! > > > > import Data.Time (DiffTime, utctDayTime, getCurrentTime) > > import Foreign (ForeignPtr, Int64, Ptr, mallocForeignPtr, withForeignPtr) > > import Foreign.Storable (sizeOf, peek, poke) > > import GHC.IO.Handle (Handle, BufferMode(NoBuffering), hClose, hGetBuf, > hSetBuffering, hPutBuf) > > import Network (Socket, HostName, PortID(PortNumber), PortNumber, > accept, connectTo, listenOn, withSocketsDo) > > import System.Console.GetOpt (ArgOrder(Permute), ArgDescr(..), > OptDescr(..), getOpt, usageInfo) > > import System.Environment (getArgs) > > > > data Flag = Client String | Server > > deriving Show > > > > -- Command line arguments for server and client mode. > > > > options :: [OptDescr Flag] > > options = > > [ Option ['c'] ["client"] (ReqArg Client "HOST") "Connect to host as > client." > > , Option ['s'] ["server"] (NoArg Server) "Run as server." > > ] > > > > perfOpts :: [String] -> IO [Flag] > > perfOpts argv = > > case getOpt Permute options argv of > > ([], [], []) -> ioError (userError ("At least one Option is needed." > ++ usageInfo "" options)) > > (o, [], []) -> return o > > (_, _, errs) -> ioError (userError (concat errs ++ usageInfo "" > options)) > > > > -- Some constants > > > > port = PortNumber 8456 > > type Trans = Int64 > > numBytes = sizeOf (0 :: Trans) > > inital = -128 :: Trans > > intermediate = 0 :: Trans > > final = 127 :: Trans > > > > makePtr = mallocForeignPtr :: IO (ForeignPtr Trans) > > > > -- The client connects to the server, initializes the connection > > -- by sending initial, sends then for the amount of at least > > -- 10 secs as much intermediate (0's) as possible and finally > > -- sends final. > > > > runClient :: String -> IO () > > runClient host = do > > print ("Running as client connecting to " ++ host) > > hdl <- initClient host port > > ptr <- makePtr > > fillInitial ptr > > withForeignPtr ptr (sendBuf hdl) > > fillIntermediate ptr > > curTime <- fmap utctDayTime getCurrentTime > > (sentBytes, time) <- sendIntermediateAndFinal ptr hdl curTime 10 0 > > print ("Sent " ++ show sentBytes ++ " Bytes in " ++ show time ++ " > seconds.") > > hClose hdl > > > > initClient :: HostName -> PortID -> IO Handle > > initClient host port = withSocketsDo $ do > > hdl <- connectTo host port > > hSetBuffering hdl NoBuffering > > return hdl > > > > sendIntermediateAndFinal :: ForeignPtr Trans -> Handle -> DiffTime -> > DiffTime -> Int -> IO (Int, DiffTime) > > sendIntermediateAndFinal ptr hdl start duration sent = do > > curTime <- fmap utctDayTime getCurrentTime > > if (curTime - start) > duration > > then do fillFinal ptr > > withForeignPtr ptr (sendBuf hdl) > > finishedTime <- fmap utctDayTime getCurrentTime > > return (sent + numBytes, finishedTime - start) > > else do withForeignPtr ptr (sendBuf hdl) > > sendIntermediateAndFinal ptr hdl start duration (sent + > numBytes) > > > > sendBuf :: Handle -> Ptr Trans -> IO () > > sendBuf hdl buf = hPutBuf hdl buf numBytes > > > > fillPtr :: Trans -> ForeignPtr Trans -> IO () > > fillPtr num ptr = withForeignPtr ptr (\p -> poke p num) > > > > fillInitial = fillPtr inital > > fillIntermediate = fillPtr intermediate > > fillFinal = fillPtr final > > > > -- The server simply accepts connections, receives what it can get > > -- and adds up the received bytes and transmission time. > > > > runServer :: IO () > > runServer = do > > print "Running as server." > > initServer port >>= handleConnection > > > > initServer :: PortID -> IO Socket > > initServer port = withSocketsDo $ listenOn port > > > > handleConnection :: Socket -> IO () > > handleConnection socket = do > > (hdl, host, port) <- acceptConnection socket > > print ("Connection from " ++ host) > > ptr <- makePtr > > (num, bytes) <- receive ptr hdl > > curTime <- fmap utctDayTime getCurrentTime > > if num == inital > > then do (received, time) <- receiveData ptr hdl curTime 0 > > print ("Received " ++ show received ++ " in " ++ show time > ++ " seconds.") > > hClose hdl > > handleConnection socket > > else do print ("ERR: Expected " ++ show inital ++ " got " ++ show > num) > > hClose hdl > > handleConnection socket > > > > acceptConnection :: Socket -> IO (Handle, HostName, PortNumber) > > acceptConnection socket = do > > (hdl, host, port) <- accept socket > > hSetBuffering hdl NoBuffering > > return (hdl, host, port) > > > > receiveData :: ForeignPtr Trans -> Handle -> DiffTime -> Int -> IO (Int, > DiffTime) > > receiveData ptr hdl started received = do > > (num, bytes) <- receive ptr hdl > > if num /= final > > then receiveData ptr hdl started (received + bytes) > > else do curTime <- fmap utctDayTime getCurrentTime > > return (received + bytes, curTime - started) > > > > receive :: ForeignPtr Trans -> Handle -> IO (Trans, Int) > > receive ptr hdl = do > > withForeignPtr ptr (\p -> hGetBuf hdl p numBytes) > > num <- withForeignPtr ptr peek > > return (num, numBytes) > > > > -- The main routine decides whether to run as server or client. > > > > main :: IO () > > main = do > > opts <- getArgs >>= perfOpts > > if length opts /= 1 > > then ioError (userError ("Too many arguments!" ++ usageInfo "" > options)) > > else > > case head opts of > > Server -> runServer > > Client host -> runClient host > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From thbach at students.uni-mainz.de Sat Nov 9 13:08:55 2013 From: thbach at students.uni-mainz.de (Thomas Bach) Date: Sat, 9 Nov 2013 14:08:55 +0100 Subject: [Haskell-beginners] IPerf in Haskell doesn't perform In-Reply-To: References: <527BB47F.40406@students.uni-mainz.de> Message-ID: <1384002535.9233.7.camel@ilxwinb01> On Thu, 2013-11-07 at 14:55 -0800, Bob Ippolito wrote: > I took your code and made a few style cleanups so that hlint wouldn't > complain and so that it would be easier to read. Being able to see those changes you made one by one on github.com was very instructive. Thanks! > > The space leak is a strictness issue that is common for Haskell > beginners to do. [?] Interesting. I wouldn't have thought of that. So, the space leak is avoided. Now, how do I get this thing to perform? Profiling the program is probably the way to go. Hopefully I find the time for this this week end. Regards, Thomas. > From abbasakbar at hushmail.com Tue Nov 12 18:18:34 2013 From: abbasakbar at hushmail.com (abbasakbar at hushmail.com) Date: Tue, 12 Nov 2013 18:18:34 +0000 Subject: [Haskell-beginners] Fake Conferences CSCI and WORLDCOMP of Hamid Arabnia Message-ID: <20131112181834.4241B6017C@smtp.hushmail.com> Fake Conferences CSCI and WORLDCOMP of Hamid Arabnia Hamid Arabnia from University of Georgia is well known for his fake WORLDCOMP conferences https://sites.google.com/site/worlddump1 or https://sites.google.com/site/dumpconf Hamid Arabnia understood that he cannot deceive researchers anymore using his WORLDCOMP. Hamid Arabnia (Guru of Fake Conferences and champion of academic scam) has recently started 2014 International Conference on Computational Science and Computational Intelligence (CSCI'14) http://www.americancse.org to deceive researchers further. CSCI'14 is started under the title of ?American Council on Science and Education? which is a dummy corporation (does not exist anywhere in the world). Hamid Arabnia buried his name in the list of names of other innocent steering and program committee members of CSCI?14 to avoid any special attention. He knows that if his name is given any special attention then researchers immediately know that the conference is fake due to his ?track record? with WORLDCOMP. Hamid Arabnia (the money hungry beast) spoiled the reputations and careers of many authors and committee members involved in his infamous WORLDCOMP for more than a decade and he is now ready to do the same using CSCI. Interestingly, CSCI is scheduled to be held at the same venue where WORLDCOMP was held until 2012. Hamid Arabnia claimed that CSCI proceedings will be published by IEEE but no one knows if IEEE really publishes. Many scholars have already sent emails to IEEE protesting for the unethical behavior of Hamid Arabnia and for the new series of his bogus conferences CSCI. CSCI paper submission deadline will be extended multiple times as usual. Do not spoil your resume by submitting your papers in this bogus conference CSCI which will not be held beyond 2014. Sincerely, Many researchers cheated by Hamid Arabnia conferences From byorgey at seas.upenn.edu Thu Nov 14 13:59:11 2013 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Thu, 14 Nov 2013 08:59:11 -0500 Subject: [Haskell-beginners] Constrained polymorphic functions as natural transformations In-Reply-To: References: Message-ID: <20131114135911.GA31874@seas.upenn.edu> Hi Matt, You have some cool ideas here --- though I think there are a few places what you say doesn't quite make sense, but I think you're on the right track. One thing to note first is that the formalism of natural transformations only covers *some* but not *all* polymorphic functions. For example, there is no way to view fix :: (a -> a) -> a as a natural transformation, because (a -> a) does not correspond to a functor over a. In general one must consider what are called *di*natural transformations. (I ought to write a blog post about this.) In any case, this is a bit of a digression---simple natural transformations suffice for a great many "real world" examples---but I thought I would mention it in case you want to look it up later. On Wed, Oct 30, 2013 at 09:50:03AM +0000, Matt R wrote: > I read this excellent blog article on natural transformations[1], which > helped me gain one intuition as to what they are: "functions that don't > make too many assumptions about their arguments". In the article, natural > transformations make "no assumptions at all" about their arguments. > However, it's often the case that a Haskell function will require a type > argument constrained by a type class, e.g. show :: Show a => a -> String. I > wondered if it was possible to characterise these functions using category > theory too. Below is my attempt, and I'm hoping people can tell me whether > I'm in the right ballpark (or point me in the direction of a better > ball-park...) > > For a particular type class T, we can form a subcategory Hask_T of Hask > consisting of all the instances of the type class as objects, with the > arrows just those functions that "commute" with the signature of the type > class. For example, in Hask_Show, the arrows would be all the functions f: > A -> B such that: > > show == show . f > > Or for Data.Monoid, all the monoid homomorphisms f: > > mappend (f x) (f y) == f (mappend x y) > mempty == f mempty Sounds good so far. This seems like a reasonable definition of a category, and an interesting one to study. > In general, for any type class, we can formulate two functors f and g and a > function sig :: f a -> g a that captures the operations in the type class, > and then the condition is that: > > fmap f . sig == sig . fmap f. Note that you can't always characterize a type class by a single function like this. For example, consider class Foo a where bar :: Int -> a baz :: a -> Int There is no way to pick functors f and g such that a Foo dictionary is equivalent to f a -> g a. I would be willing to believe that there is something interesting to say about those type classes which one *can* characterize in this way, but I don't know what it might be. > Then we have that the polymorphic functions with a type class constraint of > T are just the same thing as natural transformations in this subcategory > Hask_T. This doesn't really make sense. If a natural transformation consists of a family of arrows which all live in Hask_T, then all those arrows must (by definition) commute with the type class signature. But consider, for example, the function data Foo = Foo | Bar -- no Show instance! f :: Show a => a -> Foo f a | show a == "woz" = Foo | otherwise = Bar This f certainly does not satisfy show == show . f -- that isn't even well-typed as Foo doesn't have a Show instance; and if it did it would be easy to make a Show instance for which that equation didn't hold. Interpreting a type class constraint as determining what category we are living in is quite appealing, and I have seen this approach taken informally especially when talking about classes such as Eq and Ord. However, I have never seen it spelled out and I am not sure what the right way to do it is in general. Another approach would be to simply consider a type class constraint equivalent to a dictionary argument, as in Show a => a -> Foo === Show a -> a -> Foo === (a -> String) -> (a -> Foo) which we can see as a natural transformation between the (contravariant) functors (_ -> String) and (_ -> Foo). -Brent > Is the above correct / along the right lines? > > Thanks, > > -- Matt > > [1] "You Could Have Defined Natural Transformations", > http://blog.sigfpe.com/2008/05/you-could-have-defined-natural.html > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners From poczta at emanuelkoczwara.pl Thu Nov 14 20:05:41 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Thu, 14 Nov 2013 21:05:41 +0100 Subject: [Haskell-beginners] POSIX signals and deamons Message-ID: <52852D15.40305@emanuelkoczwara.pl> Hi, I'm trying to create a simple daemon with hdaemonize. The deamon runs ok, but i'm having trouble with signals. Here is my test case: import Control.Monad import Control.Concurrent import System.Posix.Syslog import System.Posix.Signals import System.Posix.Daemonize main = daemonize $ do withSyslog "my-test-daemon" [PID] DAEMON $ syslog Info "daemon started" installHandler sigKILL (Catch killHandler) Nothing forever $ threadDelay 1000 killHandler = withSyslog "my-test-daemon" [PID] DAEMON $ do syslog Info "kill signal received" When I run it: $ ./test $ Everything works great: $ ps aux | grep test emanuel 12790 2.6 0.0 6552 852 ? S 20:57 0:00 ./test and: # tail /var/log/daemon.log Nov 14 20:52:06 emanuel-laptop my-test-daemon[12689]: daemon started when I do: $ kill -9 12790 process no longer exist: $ ps aux | grep test $ but/var/log/daemon.log doesn't change: # tail /var/log/daemon.log Nov 14 20:52:06 emanuel-laptop my-test-daemon[12689]: daemon started It looks like my sigKILL handler isn't called, why? Thanks, Emanuel From allbery.b at gmail.com Thu Nov 14 20:10:17 2013 From: allbery.b at gmail.com (Brandon Allbery) Date: Thu, 14 Nov 2013 15:10:17 -0500 Subject: [Haskell-beginners] POSIX signals and deamons In-Reply-To: <52852D15.40305@emanuelkoczwara.pl> References: <52852D15.40305@emanuelkoczwara.pl> Message-ID: On Thu, Nov 14, 2013 at 3:05 PM, Emanuel Koczwara wrote: > installHandler sigKILL (Catch killHandler) Nothing > This should really have thrown an exception, because SIGKILL cannot be trapped, blocked, or ignored per POSIX. Maybe you want SIGTERM? -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From poczta at emanuelkoczwara.pl Thu Nov 14 20:24:06 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Thu, 14 Nov 2013 21:24:06 +0100 Subject: [Haskell-beginners] POSIX signals and deamons In-Reply-To: References: <52852D15.40305@emanuelkoczwara.pl> Message-ID: <52853166.4020701@emanuelkoczwara.pl> Hi, W dniu 14.11.2013 21:10, Brandon Allbery pisze: > On Thu, Nov 14, 2013 at 3:05 PM, Emanuel Koczwara > > wrote: > > installHandler sigKILL (Catch killHandler) Nothing > > > This should really have thrown an exception, because SIGKILL cannot be > trapped, blocked, or ignored per POSIX. Maybe you want SIGTERM? You have right, sigTERM works as expected. Thank you. Emanuel -------------- next part -------------- An HTML attachment was scrubbed... URL: From robert.krahn at gmail.com Mon Nov 18 00:47:58 2013 From: robert.krahn at gmail.com (Robert Krahn) Date: Sun, 17 Nov 2013 18:47:58 -0600 Subject: [Haskell-beginners] understanding type classes and class constraints Message-ID: Hi everyone, I'm currently enjoying to learn Haskell and came upon a problem I don't understand: Motivated by the Learn you a Haskell / yes-no typeclass example I tried to create a simple "Tester" type class: class Tester a where test :: a -> Bool I wasn't to define the rules when test returns True/False for various types, e.g. instance Tester Integer where test 0 = False test _ = True For the Maybe instance I want to delegate to the value of Just and add a class constraint: instance (Tester m) => Tester (Maybe m) where test Nothing = False test (Just x) = test x It compiles nicely and works for Just values test (Just 3) -- True test (Just 0) -- False But test Nothing gives me No instance for (Tester a0) arising from a use of `test' The type variable `a0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Tester m => Tester (Maybe m) instance Tester Integer In the expression: test Nothing Could you please enlighten me what's going on and how to fix my code? Thank you! Robert -------------- next part -------------- An HTML attachment was scrubbed... URL: From orblivion at gmail.com Mon Nov 18 00:54:45 2013 From: orblivion at gmail.com (Dan Krol) Date: Sun, 17 Nov 2013 16:54:45 -0800 Subject: [Haskell-beginners] understanding type classes and class constraints In-Reply-To: References: Message-ID: When you run "test Nothing", ghc doesn't know what type Nothing is. Just 0, ghc can deduce is a Maybe Integer. Nothing can be Maybe Integer, Maybe (Maybe Integer), Maybe Char, etc. Try running: test (Nothing :: Maybe Integer) On Sun, Nov 17, 2013 at 4:47 PM, Robert Krahn wrote: > Hi everyone, > > I'm currently enjoying to learn Haskell and came upon a problem I don't > understand: > > Motivated by the Learn you a Haskell / yes-no typeclass example I tried to > create a simple "Tester" type class: > > class Tester a where > test :: a -> Bool > > I wasn't to define the rules when test returns True/False for various > types, e.g. > > instance Tester Integer where > test 0 = False > test _ = True > > For the Maybe instance I want to delegate to the value of Just and add a > class constraint: > > instance (Tester m) => Tester (Maybe m) where > test Nothing = False > test (Just x) = test x > > It compiles nicely and works for Just values > test (Just 3) -- True > test (Just 0) -- False > > But > test Nothing > > gives me > No instance for (Tester a0) arising from a use of `test' > The type variable `a0' is ambiguous > Possible fix: add a type signature that fixes these type variable(s) > Note: there are several potential instances: > instance Tester m => Tester (Maybe m) > instance Tester Integer > In the expression: test Nothing > > Could you please enlighten me what's going on and how to fix my code? > > Thank you! > Robert > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From orblivion at gmail.com Mon Nov 18 00:57:02 2013 From: orblivion at gmail.com (Dan Krol) Date: Sun, 17 Nov 2013 16:57:02 -0800 Subject: [Haskell-beginners] understanding type classes and class constraints In-Reply-To: References: Message-ID: I guess I see the intuitive confusion. It shouldn't matter what type Nothing is, it should always return False. But ghc doesn't like to give results of a determined type (Bool) based on operations put on values of undetermined type (Maybe a). On Sun, Nov 17, 2013 at 4:54 PM, Dan Krol wrote: > When you run "test Nothing", ghc doesn't know what type Nothing is. Just > 0, ghc can deduce is a Maybe Integer. Nothing can be Maybe Integer, Maybe > (Maybe Integer), Maybe Char, etc. > > Try running: > > test (Nothing :: Maybe Integer) > > > On Sun, Nov 17, 2013 at 4:47 PM, Robert Krahn wrote: > >> Hi everyone, >> >> I'm currently enjoying to learn Haskell and came upon a problem I don't >> understand: >> >> Motivated by the Learn you a Haskell / yes-no typeclass example I tried >> to create a simple "Tester" type class: >> >> class Tester a where >> test :: a -> Bool >> >> I wasn't to define the rules when test returns True/False for various >> types, e.g. >> >> instance Tester Integer where >> test 0 = False >> test _ = True >> >> For the Maybe instance I want to delegate to the value of Just and add a >> class constraint: >> >> instance (Tester m) => Tester (Maybe m) where >> test Nothing = False >> test (Just x) = test x >> >> It compiles nicely and works for Just values >> test (Just 3) -- True >> test (Just 0) -- False >> >> But >> test Nothing >> >> gives me >> No instance for (Tester a0) arising from a use of `test' >> The type variable `a0' is ambiguous >> Possible fix: add a type signature that fixes these type variable(s) >> Note: there are several potential instances: >> instance Tester m => Tester (Maybe m) >> instance Tester Integer >> In the expression: test Nothing >> >> Could you please enlighten me what's going on and how to fix my code? >> >> Thank you! >> Robert >> >> _______________________________________________ >> Beginners mailing list >> Beginners at haskell.org >> http://www.haskell.org/mailman/listinfo/beginners >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Mon Nov 18 00:57:27 2013 From: allbery.b at gmail.com (Brandon Allbery) Date: Sun, 17 Nov 2013 19:57:27 -0500 Subject: [Haskell-beginners] understanding type classes and class constraints In-Reply-To: References: Message-ID: On Sun, Nov 17, 2013 at 7:47 PM, Robert Krahn wrote: > instance Tester Integer where > test 0 = False > test _ = True > > For the Maybe instance I want to delegate to the value of Just and add a > class constraint: > > instance (Tester m) => Tester (Maybe m) where > test Nothing = False > test (Just x) = test x > > It compiles nicely and works for Just values > test (Just 3) -- True > test (Just 0) -- False > > But > test Nothing > > gives me > No instance for (Tester a0) arising from a use of `test' > Several things are happening here. First is that numbers undergo defaulting; with nothing else to specify the type of `3` or `0`, they default to Integer and all is well. This cannot be said of `Nothing`; it needs to pick an instance, but `Nothing` doesn't give it anything to work from. "But I only have an instance for Integer!" Typeclasses work under the "open world assumption": a typeclass could be added at any time, so it cannot commit to a given typeclass instance simply because it only happens to know of one valid instance. In particular, it cannot conclude that `Nothing` is of type `Maybe Integer` solely because it happens to only be aware of a `Tester Integer` instance. (Instances are program global and cannot be hidden, so not making the open world assumption could easily cause programs to completely change their meaning with the addition of a single additional instance *anywhere* in that program, even if not imported to that module.) -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: From robert.krahn at gmail.com Mon Nov 18 02:52:32 2013 From: robert.krahn at gmail.com (Robert Krahn) Date: Sun, 17 Nov 2013 20:52:32 -0600 Subject: [Haskell-beginners] understanding type classes and class constraints In-Reply-To: References: Message-ID: Thanks a lot for the thorough and quick explanations! On Sun, Nov 17, 2013 at 6:57 PM, Brandon Allbery wrote: > On Sun, Nov 17, 2013 at 7:47 PM, Robert Krahn wrote: > >> instance Tester Integer where >> test 0 = False >> test _ = True >> >> For the Maybe instance I want to delegate to the value of Just and add a >> class constraint: >> >> instance (Tester m) => Tester (Maybe m) where >> test Nothing = False >> test (Just x) = test x >> >> It compiles nicely and works for Just values >> test (Just 3) -- True >> test (Just 0) -- False >> >> But >> test Nothing >> >> gives me >> No instance for (Tester a0) arising from a use of `test' >> > > Several things are happening here. First is that numbers undergo > defaulting; with nothing else to specify the type of `3` or `0`, they > default to Integer and all is well. > > This cannot be said of `Nothing`; it needs to pick an instance, but > `Nothing` doesn't give it anything to work from. > > "But I only have an instance for Integer!" Typeclasses work under the > "open world assumption": a typeclass could be added at any time, so it > cannot commit to a given typeclass instance simply because it only happens > to know of one valid instance. In particular, it cannot conclude that > `Nothing` is of type `Maybe Integer` solely because it happens to only be > aware of a `Tester Integer` instance. > > (Instances are program global and cannot be hidden, so not making the open > world assumption could easily cause programs to completely change their > meaning with the addition of a single additional instance *anywhere* in > that program, even if not imported to that module.) > > -- > brandon s allbery kf8nh sine nomine > associates > allbery.b at gmail.com > ballbery at sinenomine.net > unix, openafs, kerberos, infrastructure, xmonad > http://sinenomine.net > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From poczta at emanuelkoczwara.pl Sun Nov 24 13:32:40 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Sun, 24 Nov 2013 14:32:40 +0100 Subject: [Haskell-beginners] FlexibleInstances Message-ID: <5291FFF8.1010808@emanuelkoczwara.pl> Hi, I have very simple code: class XmlValue a where toValue :: a -> String instance XmlValue String where toValue _ = "lorem" It gives followingerror: Illegal instance declaration for `XmlValue String' (All instance types must be of the form (T t1 ... tn) where T is not a synonym.Use -XTypeSynonymInstancesif you want to disable this.) So, maybe I'll removethat synonym: instance XmlValue [Char] where toValue _ = "lorem" This gives following error: Illegal instance declaration for `XmlValue [Char]' (All instance types must be of the form (T a1 ... an) where a1 ... an are *distinct type variables*, and each type variable appears at most once in the instance head. Use -XFlexibleInstancesif you want to disable this.) So, maybe I'll try to use that (T a1 ... an)form: instance XmlValue ([] String) where toValue _ = "lorem" Illegal instance declaration for `XmlValue [String]' (All instance types must be of the form (T a1 ... an) where a1 ... an are *distinct type variables*, and each type variable appears at most once in the instance head. Use -XFlexibleInstancesif you want to disable this.) Ok. Maybe I'll try to enable FlexibleInstanceswith {-# LANGUAGE FlexibleInstances #-} Ok, this works, but: http://stackoverflow.com/questions/15285822/cant-make-string-an-instance-of-a-class-in-haskell(second answer): " However, Haskell98 forbids this type of typeclass in order to keep things simple and to make it harder for people to write overlapping instances like | instance Slang[a] where -- Strings would also fit this definition. slangify list= "some list" "| Ok, that's bad. But I want only [Char], [a] shouldn't work. https://ghc.haskell.org/trac/haskell-prime/wiki/FlexibleInstances says, that I'll get all or nothing. I want to enable "instance [Char] where..." but disable "instance [a] where...". Is it possible? Thanks, Emanuel -------------- next part -------------- An HTML attachment was scrubbed... URL: From plredmond at gmail.com Sun Nov 24 21:49:52 2013 From: plredmond at gmail.com (Patrick Redmond) Date: Mon, 25 Nov 2013 10:49:52 +1300 Subject: [Haskell-beginners] 'read' throws; why not maybe or either? Message-ID: Is there a variation of 'read' which uses Maybe or Either to handle failure instead of an exception? -------------- next part -------------- An HTML attachment was scrubbed... URL: From fuuzetsu at fuuzetsu.co.uk Sun Nov 24 21:57:54 2013 From: fuuzetsu at fuuzetsu.co.uk (Mateusz Kowalczyk) Date: Sun, 24 Nov 2013 21:57:54 +0000 Subject: [Haskell-beginners] 'read' throws; why not maybe or either? In-Reply-To: References: Message-ID: <52927662.9060609@fuuzetsu.co.uk> On 24/11/13 21:49, Patrick Redmond wrote: > Is there a variation of 'read' which uses Maybe or Either to handle > failure instead of an exception? > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > See http://stackoverflow.com/questions/5121371/how-to-catch-a-no-parse-exception-from-the-read-function-in-haskell -- Mateusz K. From anthony_clayden at clear.net.nz Sun Nov 24 22:02:21 2013 From: anthony_clayden at clear.net.nz (AntC) Date: Sun, 24 Nov 2013 22:02:21 +0000 (UTC) Subject: [Haskell-beginners] FlexibleInstances References: <5291FFF8.1010808@emanuelkoczwara.pl> Message-ID: > Emanuel Koczwara emanuelkoczwara.pl> writes: He Emanuel, you're doing well. Hardly anyone these days sticks to Haskell 98; and really there's no need to. (What you're trying to do can be achieved with H98, but would need some not-so-user-friendly coding.) > > I want to enable "instance [Char] where..." but disable "instance [a] where...". Is it possible? > Yes, you're almost there. You do need FlexibleInstances to be able to put [Char]. To ban [a], you need to ban overlapping instances. {-# LANGUAGE NoOverlappingInstances #-} (Usually overlapping instances is on by default.) You're next error meesage is probably going to be, Illegal overlapping instance declaration for ... Avoiding them is subtle, but a valuable discipline ;-) HTH From poczta at emanuelkoczwara.pl Sun Nov 24 22:24:11 2013 From: poczta at emanuelkoczwara.pl (Emanuel Koczwara) Date: Sun, 24 Nov 2013 23:24:11 +0100 Subject: [Haskell-beginners] FlexibleInstances In-Reply-To: References: <5291FFF8.1010808@emanuelkoczwara.pl> Message-ID: <52927C8B.1050205@emanuelkoczwara.pl> W dniu 24.11.2013 23:02, AntC pisze: > Yes, you're almost there. > You do need FlexibleInstances to be able to put [Char]. > > To ban [a], you need to ban overlapping instances. > {-# LANGUAGE NoOverlappingInstances #-} > > (Usually overlapping instances is on by default.) > > You're next error meesage is probably going to be, > Illegal overlapping instance declaration for ... > > Avoiding them is subtle, but a valuable discipline ;-) > > HTH Thanks, exactly what I wanted :) Regards, Emanuel From toad3k at gmail.com Sun Nov 24 22:43:50 2013 From: toad3k at gmail.com (David McBride) Date: Sun, 24 Nov 2013 17:43:50 -0500 Subject: [Haskell-beginners] 'read' throws; why not maybe or either? In-Reply-To: References: Message-ID: You might be interested in the 'safe' package. It has a function in it called readMay, along with a lot of other useful minor omissions from prelude. http://hackage.haskell.org/package/Safe-0.1/docs/Safe.html On Sun, Nov 24, 2013 at 4:49 PM, Patrick Redmond wrote: > Is there a variation of 'read' which uses Maybe or Either to handle > failure instead of an exception? > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From byorgey at seas.upenn.edu Mon Nov 25 10:43:20 2013 From: byorgey at seas.upenn.edu (Brent Yorgey) Date: Mon, 25 Nov 2013 05:43:20 -0500 Subject: [Haskell-beginners] FlexibleInstances In-Reply-To: References: <5291FFF8.1010808@emanuelkoczwara.pl> Message-ID: <20131125104319.GA1954@seas.upenn.edu> On Sun, Nov 24, 2013 at 10:02:21PM +0000, AntC wrote: > > Emanuel Koczwara emanuelkoczwara.pl> writes: > > He Emanuel, you're doing well. > Hardly anyone these days sticks to Haskell 98; > and really there's no need to. > (What you're trying to do can be achieved with H98, > but would need some not-so-user-friendly coding.) > > > > > I want to enable "instance [Char] where..." but disable "instance [a] > where...". Is it possible? > > > > Yes, you're almost there. > You do need FlexibleInstances to be able to put [Char]. > > To ban [a], you need to ban overlapping instances. > {-# LANGUAGE NoOverlappingInstances #-} > > (Usually overlapping instances is on by default.) No, it's not. -Brent From rus314 at gmail.com Mon Nov 25 15:28:32 2013 From: rus314 at gmail.com (Alexandr M) Date: Mon, 25 Nov 2013 17:28:32 +0200 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers Message-ID: Hello ! Could anybody explain me how to calculate simple moving average of a list ? I have found several examples in internet but I completely don't understand how it works. Basically it's necessary to iterate over the list of real numbers and calculate average values over last n items in the list. I just can't imagine how to do it without loops. -- Best regards, Alex -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael at orlitzky.com Mon Nov 25 16:37:43 2013 From: michael at orlitzky.com (Michael Orlitzky) Date: Mon, 25 Nov 2013 11:37:43 -0500 Subject: [Haskell-beginners] 'read' throws; why not maybe or either? In-Reply-To: References: Message-ID: <52937CD7.4080503@orlitzky.com> On 11/24/2013 04:49 PM, Patrick Redmond wrote: > Is there a variation of 'read' which uses Maybe or Either to handle > failure instead of an exception? readMaybe: http://hackage.haskell.org/package/base-4.6.0.1/docs/Text-Read.html#v:readMaybe Prelude> import Text.Read (readMaybe) Prelude Text.Read> readMaybe "Hello, World!" :: Maybe Int Nothing Prelude Text.Read> readMaybe "45" :: Maybe Int Just 45 From chaddai.fouche at gmail.com Mon Nov 25 18:33:51 2013 From: chaddai.fouche at gmail.com (=?UTF-8?B?Q2hhZGRhw68gRm91Y2jDqQ==?=) Date: Mon, 25 Nov 2013 19:33:51 +0100 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: Message-ID: On Mon, Nov 25, 2013 at 4:28 PM, Alexandr M wrote: > Hello ! > > Could anybody explain me how to calculate simple moving average of a list ? > > I have found several examples in internet but I completely don't > understand how it works. > > Basically it's necessary to iterate over the list of real numbers and > calculate average values over last n items in the list. > > I just can't imagine how to do it without loops. > Who needs loops when you have recursion, or more to the point good combinators ! You can do it in a few lines using only splitAt, length (to check the result of splitAt), zip, and scanl. (and sum, +, - and /, of course). Ask again, if that's not enough. -- Jeda? -------------- next part -------------- An HTML attachment was scrubbed... URL: From zhiwudazhanjiangshi at gmail.com Tue Nov 26 01:50:58 2013 From: zhiwudazhanjiangshi at gmail.com (yi lu) Date: Tue, 26 Nov 2013 09:50:58 +0800 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: Message-ID: It reminds me of k-means. On Tue, Nov 26, 2013 at 2:33 AM, Chadda? Fouch? wrote: > On Mon, Nov 25, 2013 at 4:28 PM, Alexandr M wrote: > >> Hello ! >> >> Could anybody explain me how to calculate simple moving average of a list >> ? >> >> I have found several examples in internet but I completely don't >> understand how it works. >> >> Basically it's necessary to iterate over the list of real numbers and >> calculate average values over last n items in the list. >> >> I just can't imagine how to do it without loops. >> > > Who needs loops when you have recursion, or more to the point good > combinators ! You can do it in a few lines using only splitAt, length (to > check the result of splitAt), zip, and scanl. (and sum, +, - and /, of > course). > > Ask again, if that's not enough. > > -- > Jeda? > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From plredmond at gmail.com Tue Nov 26 04:31:22 2013 From: plredmond at gmail.com (Patrick Redmond) Date: Tue, 26 Nov 2013 17:31:22 +1300 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: Message-ID: In functional programming, loops are implemented using recursion and tailcalls. You have the power of loops beyond what "for" and "while" can express. On Tuesday, November 26, 2013, Alexandr M wrote: > Hello ! > > Could anybody explain me how to calculate simple moving average of a list ? > > I have found several examples in internet but I completely don't > understand how it works. > > Basically it's necessary to iterate over the list of real numbers and > calculate average values over last n items in the list. > > I just can't imagine how to do it without loops. > > -- > Best regards, > Alex > -------------- next part -------------- An HTML attachment was scrubbed... URL: From plredmond at gmail.com Tue Nov 26 04:32:32 2013 From: plredmond at gmail.com (Patrick Redmond) Date: Tue, 26 Nov 2013 17:32:32 +1300 Subject: [Haskell-beginners] 'read' throws; why not maybe or either? In-Reply-To: <52937CD7.4080503@orlitzky.com> References: <52937CD7.4080503@orlitzky.com> Message-ID: Thanks all! I was able to make use of readEither to do just what I wanted. On Tuesday, November 26, 2013, Michael Orlitzky wrote: > On 11/24/2013 04:49 PM, Patrick Redmond wrote: > > Is there a variation of 'read' which uses Maybe or Either to handle > > failure instead of an exception? > > readMaybe: > > > http://hackage.haskell.org/package/base-4.6.0.1/docs/Text-Read.html#v:readMaybe > > Prelude> import Text.Read (readMaybe) > Prelude Text.Read> readMaybe "Hello, World!" :: Maybe Int > Nothing > Prelude Text.Read> readMaybe "45" :: Maybe Int > Just 45 > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ozgurakgun at gmail.com Tue Nov 26 14:47:48 2013 From: ozgurakgun at gmail.com (Ozgur Akgun) Date: Tue, 26 Nov 2013 14:47:48 +0000 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: Message-ID: Hi Alex. On 25 November 2013 15:28, Alexandr M wrote: > Could anybody explain me how to calculate simple moving average of a list ? > > I have found several examples in internet but I completely don't > understand how it works. > > Basically it's necessary to iterate over the list of real numbers and > calculate average values over last n items in the list. > > I just can't imagine how to do it without loops. > Maybe we can use "inits" from "Data.List". Prelude> import Data.List Prelude Data.List> mapM_ print $ inits [1..10] [] [1] [1,2] [1,2,3] [1,2,3,4] [1,2,3,4,5] [1,2,3,4,5,6] [1,2,3,4,5,6,7] [1,2,3,4,5,6,7,8] [1,2,3,4,5,6,7,8,9] [1,2,3,4,5,6,7,8,9,10] Not a bad start. It gives us all the *initial segments* of a list. Now we need to keep the last n items for each of these. Let's see. Maybe we can define a function using "drop" and "length" as follows. Prelude Data.List> let lastN n xs = drop (length xs - n) xs This function should drop everything but the last n items in a list. If there are less than n items, it will return the list unchanged. Try it on a few inputs to see why this is the case. Also try "drop" on a few inputs. And the type of this function seems sensible enough: Prelude Data.List> :t lastN lastN :: Int -> [a] -> [a] Now: Prelude Data.List> mapM_ print $ map (lastN 3) $ inits [1..10] [] [1] [1,2] [1,2,3] [2,3,4] [3,4,5] [4,5,6] [5,6,7] [6,7,8] [7,8,9] [8,9,10] This seems pretty close to what you want. For each item in the list, we have a corresponding list of n items that are coming just before it. If only we had a function to calculate the average of a list of numbers, then we could: Prelude Data.List> mapM_ print $ map average $ map (lastN 3) $ inits [1..10] NaN 1.0 1.5 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 I've defined average locally here to demonstrate the use of it. I'll leave the definition of it as an exercise to you. Of course, depending on what you want to do with these averages, you can implement the same functionality in different ways. Maybe you only need the last one only or something else. I don't know. Also you can *fuse* the two maps and use only one map, but I wanted to keep things explicit. Hope this helps, Ozgur. -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael at orlitzky.com Tue Nov 26 17:11:56 2013 From: michael at orlitzky.com (Michael Orlitzky) Date: Tue, 26 Nov 2013 12:11:56 -0500 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: Message-ID: <5294D65C.5040204@orlitzky.com> On 11/25/2013 10:28 AM, Alexandr M wrote: > Hello ! > > Could anybody explain me how to calculate simple moving average of a list ? > > I have found several examples in internet but I completely don't > understand how it works. > > Basically it's necessary to iterate over the list of real numbers and > calculate average values over last n items in the list. > > I just can't imagine how to do it without loops. When you need to know the position of something in a list, one easy way to get it is to "zip" the original list with another list of "positions", [1,2,3,...]. Then when you're processing the list, you're not just dealing with some element somewhere in the list, you have the ordered pair (item, position) which you probably know what to do with. Inline below is some code that uses this idea along with a "scan" (similar to a fold) to accomplish the moving average. Here it is in action: Prelude> :l moving_average.hs [1 of 1] Compiling Main ( moving_average.hs, interpreted ) Ok, modules loaded: Main. *Main> let samples = [1,2,3,4,5] :: [Double] *Main> let mavg = moving_average samples *Main> print mavg [(1.0,1.0),(1.5,2.0),(2.0,3.0),(2.5,4.0),(3.0,5.0)] If you only want the averages (and not the positions), the positions are easy to drop: *Main> print $ map fst mavg [1.0,1.5,2.0,2.5,3.0] Code below. I've tried to avoid line wrapping, but buyer beware. module Main where -- | Create a list whose nth entry is a pair containing the average of -- the first n elements of the given samples, along with the -- position n. We use a "scan" to do this; a scan is like a fold -- except it keeps track of the intermediate values and not just the -- final one. -- -- We can use this to our advantage; the nth average is just (n-1) -- times the previous average, added to the current item, and then -- divided by n. So we will thread a pair, (average, position), -- through the list computing each average from the previous one as -- we go. -- -- The result should be a list of all averages we generated along -- the way. If you want to drop the positions from the result, you -- can simply call `map fst` on it. -- moving_average :: (Fractional a) => [a] -> [(a,a)] moving_average [] = [] moving_average samples = -- scanl1 uses the first entry of samples_pos as the first entry in -- the result. Since we don't need to do any averaging of the first -- item (it gets divided by one), this is what we want. scanl1 average samples_pos where -- The indices we'll use for the positions in the list. We use -- fromIntegral on all of them because we want to be able to -- divide by them, so they need to be converted to something -- Fractional (GHC will figure it out). positions = map fromIntegral [1..] -- The list samples_pos contains the original samples "zipped" with -- their position in the list. The entries of samples_pos should be -- pairs (x,y) where x was te original entry in the list, and y -- was its position. This lets us know which number we need to -- divide by for the average samples_pos = zip samples positions -- This is the function that does the work. It takes the previous -- (average, position) pair and the new (value, position) pair and -- uses them to generate the new (average, position). average :: (Fractional b) => (b,b) -> (b,b) -> (b,b) average (prev_avg, prev_pos) (sample, pos) = (new_avg, pos) where prev_sum = prev_avg * prev_pos new_avg = (prev_sum + sample) / pos From ky3 at atamo.com Tue Nov 26 17:54:27 2013 From: ky3 at atamo.com (Kim-Ee Yeoh) Date: Wed, 27 Nov 2013 00:54:27 +0700 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: <5294D65C.5040204@orlitzky.com> References: <5294D65C.5040204@orlitzky.com> Message-ID: On Wed, Nov 27, 2013 at 12:11 AM, Michael Orlitzky wrote: > Inline below is some code that uses this idea along with a "scan" > (similar to a fold) to accomplish the moving average. > Hi Michael, When I read OP's request, I understood it as what Ozgur had interpreted, i.e. last N items for a /constant/ N, also known as a moving window average. Your running average solution is interesting too! -- Kim-Ee -------------- next part -------------- An HTML attachment was scrubbed... URL: From etesial at gmail.com Tue Nov 26 19:32:42 2013 From: etesial at gmail.com (Alexander Morozov) Date: Tue, 26 Nov 2013 23:32:42 +0400 Subject: [Haskell-beginners] IPerf in Haskell doesn't perform In-Reply-To: <1384002535.9233.7.camel@ilxwinb01> References: <527BB47F.40406@students.uni-mainz.de> <1384002535.9233.7.camel@ilxwinb01> Message-ID: If it's still relevant... The problem is that the program sends data in 8 byte chunks. Every write results in a syscall, context switch and pushing the chunk through TCP stack, so overhead is great. BTW, using Bytestring works well enough, my similar program [1] pushes around 15Gbits through lo interface and saturates 1Gbit ethernet connection. [1] https://github.com/alexandermorozov/netperf Regards, Alexander On Sat, Nov 9, 2013 at 5:08 PM, Thomas Bach wrote: > On Thu, 2013-11-07 at 14:55 -0800, Bob Ippolito wrote: >> I took your code and made a few style cleanups so that hlint wouldn't >> complain and so that it would be easier to read. > > Being able to see those changes you made one by one on github.com was > very instructive. Thanks! > >> >> The space leak is a strictness issue that is common for Haskell >> beginners to do. [?] > > Interesting. I wouldn't have thought of that. > > So, the space leak is avoided. Now, how do I get this thing to perform? > Profiling the program is probably the way to go. Hopefully I find the > time for this this week end. > > > Regards, > > Thomas. >> > > > > _______________________________________________ > Beginners mailing list > Beginners at haskell.org > http://www.haskell.org/mailman/listinfo/beginners From michael at orlitzky.com Wed Nov 27 02:39:17 2013 From: michael at orlitzky.com (Michael Orlitzky) Date: Tue, 26 Nov 2013 21:39:17 -0500 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: References: <5294D65C.5040204@orlitzky.com> Message-ID: <52955B55.7040501@orlitzky.com> On 11/26/2013 12:54 PM, Kim-Ee Yeoh wrote: > > Hi Michael, > > When I read OP's request, I understood it as what Ozgur had interpreted, > i.e. last N items for a /constant/ N, also known as a moving window average. > > Your running average solution is interesting too! Oh, sorry. Statistics is down the hall =) You need to modify the scanl1 solution a little bit, but it should still work somewhat-efficiently only making one pass through the list and not using any partial functions. If the "window size" n is fixed, we need more information at each point in the list: 1. The item itself 2. What number we should subtract from the previous sum 3. What the previous divisor was 4. What the new divisor is (I'm assuming you want the first n items to be the running average, i.e. my first implementation.) The divisor that we'll use at each point is, [1, 2, ..., n, n, n...] and that can be zipped with the samples just like before. The other thing that we need is the item that will be "dropped" from the average. If the window is fixed, we'll be dropping one number and adding one number every time we move to a new item in the list (once we've processed n of them, at least). Before we've processed n of them, we don't want to subtract anything from the previous sum -- we want the running average. We can accomplish this by sticking n-1 zeros on the head of the samples, and zipping *that* with the samples. I haven't commented this version, but if you understand the last one, you can figure out what it does. Here's the example Ozgur used: *Main> :l moving_average.hs [1 of 1] Compiling Main ( moving_average.hs, interpreted ) Ok, modules loaded: Main. *Main> let samples = [1,2,3,4,5,6,7,8,9,10] :: [Float] *Main> moving_average 3 samples [1.0,1.5,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0] (They agree.) It can do a million items pretty quickly considering we're in ghci: *Main> let samples = [1..1000000] :: [Float] *Main> :set +s *Main> length $ moving_average 10 samples 1000000 (1.08 secs, 545400640 bytes) -------- module Main where fst3 :: (a,b,c) -> a fst3 (x, _, _) = x moving_average :: (Fractional a) => Int -> [a] -> [a] moving_average _ [] = [] moving_average n samples | n <= 0 = [] | otherwise = map fst3 $ scanl1 average sample_triples where divisors = map fromIntegral $ [1..n] ++ (repeat n) n_agos = (map fromIntegral (replicate (n-1) 0)) ++ samples sample_triples = zip3 samples divisors n_agos average :: (Fractional b) => (b,b,b) -> (b,b,b) -> (b,b,b) average (prev_avg, prev_div, dropme) (sample, divisor, n_ago) = (new_avg, divisor, n_ago) where prev_sum = prev_avg * prev_div new_avg = (prev_sum + sample - dropme) / divisor From johns at sstar.com Wed Nov 27 04:58:28 2013 From: johns at sstar.com (John Souvestre) Date: Tue, 26 Nov 2013 22:58:28 -0600 Subject: [Haskell-beginners] Simple Moving Average of a list of real numbers In-Reply-To: <52955B55.7040501@orlitzky.com> References: <5294D65C.5040204@orlitzky.com> <52955B55.7040501@orlitzky.com> Message-ID: <006a01ceeb2d$51a55b10$f4f01130$@sstar.com> > Oh, sorry. Statistics is down the hall =) There is another often used method which might be worth considering. If you don't need the absolute accuracy that the "boxcar" moving average gives, then perhaps a exponentially weighted moving average (aka: exponential filter) will do. It has the advantage of being easier to code, requiring less CPU power (normally), and needing only one variable for long term storage. There a good description at: http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average Simply put, you save only the result, not the individual sample. To update it with a new sample you first remove the "equivalent" of one sample then add your new sample. How do you remove the oldest sample? You can't, since you didn't save it. Instead you remove 1/n'th (for averaging over n samples) of the previous result, then add the new sample. If you think about it, the longer a sample has been part of the result, the less effect it has on the result - exponentially less. This is why I said it isn't as accurate as the boxcar method. But for many situations (most of the ones I've run into) it suffices and indeed can be better since it dampens (filters) step changes. As an equation: average_new = average_old - (average_old / n) + (sample_new / n) Or tweaking for efficiency: average_new = average_old + ( (sample_new - average_old) / n ) Note: You need to use floating point numbers for the calculation and resulting average, even if the samples are integers. Also, choosing a binary number for n should help speed up the division, if the math pack takes advantage of it. I realize that this doesn't directly address the question which Alex posed, but I thought that perhaps it might be of interest as an alternative. John ??? John Souvestre - New Orleans LA - (504) 454-0899 -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 6298 bytes Desc: not available URL: From patrick.browne at dit.ie Sat Nov 30 22:40:59 2013 From: patrick.browne at dit.ie (Patrick Browne) Date: Sat, 30 Nov 2013 22:40:59 +0000 Subject: [Haskell-beginners] Equality instance for lists Message-ID: <7410f2a45dd5.529a697b@dit.ie> An HTML attachment was scrubbed... URL: From allbery.b at gmail.com Sat Nov 30 23:01:14 2013 From: allbery.b at gmail.com (Brandon Allbery) Date: Sat, 30 Nov 2013 18:01:14 -0500 Subject: [Haskell-beginners] Equality instance for lists In-Reply-To: <7410f2a45dd5.529a697b@dit.ie> References: <7410f2a45dd5.529a697b@dit.ie> Message-ID: On Sat, Nov 30, 2013 at 5:40 PM, Patrick Browne wrote: > I am trying to write my own simplified class and instances for equality. > I have trouble with the equality equation for the empty list. > Even though I can use the [] == [] at the GHCi prompt I cannot use it in > my equality test. > How can I make my eq test handle empty lists while staying within the > context of my current code?. > You can't unless you include an Eq constraint on a, since Eq is what "defines" (==). In your other instance, you use Int and Int has an Eq instance. ghci can do it because of extended defaulting: it uses () for a, and there is an Eq instance for (). But this would not help you in an instance definition. -- brandon s allbery kf8nh sine nomine associates allbery.b at gmail.com ballbery at sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net -------------- next part -------------- An HTML attachment was scrubbed... URL: