Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   Show Off Your Open Source Projects (http://www.programmingforums.org/forum52.html)
-   -   Haskell tutorial: writing a blacklist engine using the Writer Monad (http://www.programmingforums.org/showthread.php?t=12973)

Mad_guy Apr 10th, 2007 10:48 PM

Haskell tutorial: writing a blacklist engine using the Writer Monad
 
I just got done the other day writing a tutorial on the Writer monad as I think I finally understand Monads ultimately (or as far as I know,) and I was wondering what some of you would think of it:

http://austin.youareinferior.net/?q=node/22

That's the link. I would appreciate any feedback and suggestions on it, since it's kinda my first real shot at doing using Monads, writing over it especially.

Arevos Apr 12th, 2007 12:37 PM

It looks pretty good, though I'm not sure why you used the Writer monad if you only have one piece of output. Is this going to tie into the packet sniffer later on? Or did you choose to use the Writer monad merely as a challenge? :)

Mad_guy Apr 13th, 2007 3:28 PM

The writer monad was merely a challenge, really. Plus since the Writer monad is particularly accustomed to accumulating results over the lifetime of a computation, and given the way the blacklist filter takes arrays in both parameters (and how it matched them), I used the Writer monad. So really, I used the Writer monad because I found it practical, and in the middle I figured out a great deal and had a lot of fun. The packet sniffer right now is being worked on in another article (and it is long, comparatively at least.)

The Blister library was going to tie into the packet sniffer, and it still might at this point. I added in support for berkeley packet filter programs to be specified (a la tcpdump,) so i figured that would be plenty robust for the beginning builds and much later versions (right now the program and article are still being worked on in juxtaposition. I've hit a bump right now so I might need to revise the tutorial and the code some, but it works really well and I'm happy with the results.) Currently I'm working on the program's argument handling and accepting options, many of which are cribbed from tcpdump's man page. So there's the possibility I may add a parameter to allow you to specify multiple regular expressions for a packet's ASCII to abide by. So that'll be fun.

If you want the code for the packet sniffer, it's on the web. Run a:

:

darcs get --set-scripts-executable http://anapnea.net/~thoughtpolice/hsns

Currently it handles no options other than a berkely packet filter, but it captures packets (with filter applied, so you do have flexibility in terms of what to capture) and prints them out readably in both Hex and ASCII. And only in about 70 lines of code.

The system administrator was nice enough to install darcs so I could use it to publish my code on the web (finally; nice considering it's a free shell too from apapnea.net.) If you just want the source code it's here: http://hpaste.org/1368. There's no tarball or executable, so you'll have to pull the repo and compile (not like that's hard.) Just be sure to run the resulting executable as root.


As a self satisfying tidbit, search results for "writer monad" on google bring my article on my blog as the #2 result. :)

Arevos Apr 13th, 2007 5:13 PM

It looks pretty good. A few quick points though:

The following code:
:

let x = map (\i -> (PCap.ifName i)) devs
net  <- PCap.lookupNet (x !! 0)
spy  <- PCap.openLive (x !! 0) 512 True 100000

Could probably be more cleanly expressed as:
:

let (x:_) = map PCap.ifName devs
net <- PCap.lookupNet x
spy <- PCap.openLive x 512 True 100000

And:
:

s  <- return $ map (\x -> if (x >= 32 && x <= 126) then x else 46) a
s' <- return $ map (\x -> chr (read $ show x)) s

Could probably be expressed as:
:

let s = [if x >= 32 && x <= 126 then chr x else '.' | x <- a]
("s <- return $ ..." is the same as "let s = ...")

Mad_guy Apr 14th, 2007 12:57 AM

Thanks for the tip. On the second piece of code though, you can't directly convert a Word8 to a Char. Example:

:

[austin@continuum ~]$ ghci
  ___        ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
Prelude> :m + Data.Word
Prelude Data.Word> let x = 48 :: Word8
Prelude Data.Word> :m + Data.Char
Prelude Data.Word Data.Char> chr x

<interactive>:1:4:
    Couldn't match expected type `Int' against inferred type `Word8'
    In the first argument of `chr', namely `x'
    In the expression: chr x
    In the definition of `it': it = chr x
Prelude Data.Word Data.Char> Leaving GHCi.
[austin@continuum ~]$


I don't like the code I had to use to get a Character out of a Word8, perhaps there's a more efficient way using Data.ByteString, for right now it works though (I may add a function to convert a word to a character since I need it several places in the code.)
For example, something like this:

:

let s = [if x >= 32 && x <= 126 then word2char x else '.' | x <- a]

I'll most likely add that to the tutorial. Thanks for both tips too. :)

Arevos Apr 14th, 2007 9:30 AM

Quote:

Originally Posted by Mad_guy (Post 126695)
Thanks for the tip. On the second piece of code though, you can't directly convert a Word8 to a Char.

I did wonder about that, which is why I put "probably" in my sentence ;)

I did a bit more digging, and it turns out that the "fromIntegral" function is your man, as it converts from one integral type to another (presumably it's integral as in integer, not as in integration):

:

import Data.Char

char :: Integral a => a -> Char
char = chr . fromIntegral

There: a much more universal char function.

Mad_guy Apr 14th, 2007 4:14 PM

:) Thanks.

I just updated the code and it now includes Command line options, TCPdump filters, and it formats the packets nicely. And at only 170 lines of code, that's not bad. You can check the latest version like all the rest.


All times are GMT -5. The time now is 2:22 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC