The Haskell Sequence - Applications
http://sequence.complete.org/taxonomy/term/12/0
enConverting a ByteString to a Double using FFI
http://sequence.complete.org/node/373
<p>ByteString, the ever-useful fast string library, has some nice functions for reading Ints which make reading in test data a breeze. However, there's no similar function for Doubles which has caused some recent troubles for me when dealing with floating point data. The C library has a function for this task: strtod. So I decided to take some older but similar FFI code and mold it into an interface to strtod.</p>
<p><code><br />
{-# LANGUAGE ForeignFunctionInterface #-}<br />
import Foreign<br />
import Foreign.C.Types<br />
import Data.ByteString.Base<br />
</code></p>
<p><code><br />
foreign import ccall unsafe "stdlib.h strtod"<br />
c_strtod :: Ptr Word8 -> Ptr (Ptr Word8) -> IO CDouble<br />
</code></p>
<p><code><br />
strtod :: ByteString -> Maybe (CDouble, ByteString)<br />
strtod str = inlinePerformIO .<br />
withForeignPtr x $ \ p -><br />
alloca (\ p_endptr -> do<br />
let p_s = p `plusPtr` s<br />
n <- c_strtod p_s p_endptr<br />
endptr <- peek p_endptr<br />
let diff = endptr `minusPtr` p_s<br />
if diff == 0<br />
then return Nothing<br />
else return $ Just (n, PS x (s + diff) (l - diff)))<br />
where (x, s, l) = toForeignPtr str<br />
</code></p>
<p>The type is chosen in particular to be convenient for usage with <code>unfoldr</code>.</p>
<p>The code probably looks more complicated than it is. Since ByteStrings are really stored as <code>ForeignPtr Word8</code> (along with start-offset and length), it is easy to grab the raw form for usage by C functions. <code>withForeignPtr</code> lets you manipulate the raw <code>Ptr Word8</code> within a function. Pointer arithmetic is performed using functions like <code>plusPtr</code>. The second parameter to strtod is actually an "out" parameter which sets a pointer to the spot it finished reading. I allocate space to store a pointer, namely a <code>Ptr (Ptr Word8)</code> and Haskell can figure out how much space it needs from the inferred type. I <code>peek</code> to retrieve the "returned" end-pointer. Then it's just a matter of putting back together the ByteString (<code>PS</code> for "Packed String") with the new offset and length.</p>
http://sequence.complete.org/node/373#commentsApplicationsTue, 18 Dec 2007 13:36:59 -0800mrd373 at http://sequence.complete.orgIs logging really this tuff with Haskell?
http://sequence.complete.org/node/368
<p>I quote: http://programming.reddit.com/info/5ze57/comments</p>
<blockquote><p>
Haskell is too weird for me (if I want to add a logging statement, I don't want to rewrite ten functions to use monads instead of the types they previously had).
</p></blockquote>
http://sequence.complete.org/node/368#commentsApplicationsThu, 08 Nov 2007 13:35:43 -0800metaperl368 at http://sequence.complete.orgThe algorithm for Discordian text encryption
http://sequence.complete.org/node/366
<p><CODE><br />
module Crypt_Discordian<br />
where</p>
<p>import List</p>
<p>vowel_list = "aeiouAEIOU"</p>
<p>is_vowel c = c `elem` vowel_list</p>
<p>move_vowels lis = move_vowels' lis [] []</p>
<p>move_vowels' [] c v = v ++ c<br />
move_vowels' (x:xs) c v<br />
| is_vowel x = move_vowels' xs c (x:v)<br />
| otherwise = move_vowels' xs (x:c) v</p>
<p>remove_spaces str = filter (\x -> x /= ' ') str</p>
<p>encrypt str = List.sort $ move_vowels $ remove_spaces str</p>
<p>{-</p>
<p>The algorithm for Discordian text encryption is given at:</p>
<p> http://www.principiadiscordia.com/book/78.php</p>
<p>After implementing this, I realized that all the early steps are a farce.</p>
<p>But anyway, here is the algorithm in case you don't enjoy tilting your<br />
head to read a page:</p>
<p>Step 1. Write out message (HAIL ERIS) and put all vowels at the end<br />
(HLRSAIEI)</p>
<p>Step 2. Reverse order (IEIASRLH)</p>
<p>Step 3. Convert to numbers (9-5-9-1-19-18-12-8)</p>
<p>Step 4. Put into numerical order (1-5-8-9-9-12-18-19)</p>
<p>Step 5. Convert back to letter (AEHIILRS)</p>
<p>This cryptographic cypher code is GUARANTEED TO BE 100% UNBREAKABLE</p>
<p>.. so says the Principia Discordia. But I think we can generate and<br />
test to break it.</p>
<p>Many thanks to kosmikus and Pseudonym for their help in developing<br />
this module</p>
<p>-}</p>
<p>{-</p>
<p>Discordians. They are a<br />
group of people who believe that spirituality is as much about<br />
disharmony as it is about harmony.</p>
<p>So, in their primary book, Principia Discorida:</p>
<p> http://principiadiscordia.com/</p>
<p>you never know what is serious and what is play. The wikipedia has<br />
more to say on them:</p>
<p> http://en.wikipedia.org/wiki/Discordian</p>
<p>-}</p>
<p></CODE></p>
http://sequence.complete.org/node/366#commentsApplicationsSun, 04 Nov 2007 08:25:47 -0800metaperl366 at http://sequence.complete.orgRevisiting board-building in chess
http://sequence.complete.org/node/361
<p>So, in my last blog, we looked at the beginnings of a chess engine. That was nearly 2 months ago. I've been kicking around some possibilities for the last few months, trying to come up with a somewhat elegant solution. Ultimately, I've wound up completely refactoring what I started with. I'll be posting more on that here within the next few weeks, but I'm really excited by how one piece came out, so I'd like to show that part at least.</p>
<p>Last time, I mentioned FEN notation for the state of a chess game. Let's look at that in a bit more detail. Here's the FEN notation for the start of a game:</p>
<p>rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1</p>
<p>You can see, there are 6 space-separated fields in this string. What I want to write is this function:</p>
<p>loadFEN :: String -> GameState</p>
<p>...which constructs the state of the game from the FEN. Now, this is notoriously tedious in most languages, but the solution in haskell looks quite elegant to me. </p>
<p>So, let's see. Each field in the FEN is going to tell us something about how to construct the GameState. The first field tells us where the pieces are, the second tells us whose turn it is, the third deals with castling statuses, etc. So we can start with an empty state, and apply multiple functions to it, based on the fields, to build up a new state. That sounds like a fold pattern to me!</p>
<p>However, this seems to be a bit tricky at first. We'll want to apply a different function for each field. That is, the first function will look at that first field and build up the actual squares on the board with pieces. The second function will parse the indicator of whose turn it is, and make that change to the state, etc. So let's start by zipping these functions up with the fields they correspond with:</p>
<pre>
loadFEN fen = foldl apply emptyGameState (zip funcs fields)
where fields = words fen
funcs = [parseBoard, parseCastleStatus]
</pre><p>
Here, I've just listed the functions for the first 2 fields, to give us an idea. The only mystery that's left is this apply function. Let's look at its type:</p>
<p>apply :: GameState -> (String -> GameState -> GameState, String) -> GameState</p>
<p>That is, it takes a current state, and a pair, consisting of a function and a field to apply it to, and a field, and returns a new state. Well, that's not so bad:</p>
<p>apply state (function, field) = function field state</p>
<p>Running this through the @pl formatter on lambdabot in #haskell gives us an ugly mess:</p>
<p>apply = (`ap` snd) . flip (flip . fst)</p>
<p>Hmm, this is interesting though, look at the flipping going on. What if we took the input in a different order? Suppose we wrote this:</p>
<p>apply (function, field) state = function field state</p>
<p>Running this through @pl gives the very elegant:</p>
<p>apply = ap fst snd</p>
<p>Thus, the final code winds up being:</p>
<pre>
loadFEN :: String -> GameState
loadFEN fen = foldl apply emptyGameState (zip funcs fields)
where fields = words fen
apply = flip (ap fst snd)
funcs = [parseBoard, parseCastleStatus]
</pre><p>
Very nifty! Now all the real work gets moved off to smaller functions, which just have to worry about the particular field they're designed to work with. Not only that, but if I only want to deal with the first few fields for now, they're the only ones I have to parse, and I'll still wind up with a valid GameState.</p>
http://sequence.complete.org/node/361#commentsApplicationsDiscussionSat, 18 Aug 2007 11:42:53 -0700chessguy361 at http://sequence.complete.orgChess in Haskell
http://sequence.complete.org/node/296
<p>I thought that since chess AI is (or, at least, has been) a hobby of mine, it would be fun and educational to write one in Haskell. And if I'm going to do that, I figure I may as well blog about it!</p>
<p>A few preliminary matters before I dive into the code. First, I make no promises as to how often I will add to this blog. A chess AI is a long project, and I don't currently have a ton of time to devote to it. Second, I intend to start very simply, and inefficiently, with data structures that I know can be improved on. Part of the fun will be refactoring it later. Finally, I fully admit to being a novice Haskeller. I've been studying it for a year or so now, but still struggle with things I should have mastered long ago. Suggestions are highly desirable.</p>
<p>Ok, let's do this! First, a few definitions:<br />
<code><br />
type Board = Array Int Piece</p>
<p>data Piece = Piece Color PieceType<br />
data Color = White | Black<br />
data PieceType = Pawn | Knight | Bishop | Rook | Queen | King<br />
</code></p>
<p>We represent a board as a simple array, indexed by Ints. This gives us O(1) access to any square. This is one area that I guarantee I will come back to, but it's simple enough to start with. Board representation is a HUGE issue with chess AI, and there are many, many things we can try with it. Anyway, we'll use a standard convention, which is to number square A1 (the square closest to white, on his left) as square 0, and H8 (on black's left) as 63. That is, the board will look like this (leading 0's added for spacing only):<br />
BLACK<br />
56 57 58 59 60 61 62 63<br />
48 49 50 51 52 53 54 55<br />
40 41 42 43 44 45 46 47<br />
32 33 34 35 36 37 38 39<br />
24 25 26 27 28 29 30 31<br />
16 17 18 19 20 21 22 23<br />
08 09 10 11 12 13 14 15<br />
00 01 02 03 04 05 06 07<br />
WHITE</p>
<p>Now a few useful little things:<br />
<code><br />
emptyBoard :: Board<br />
emptyBoard = array (0,63) []</p>
<p>piece :: Char -> Piece<br />
piece c = Piece color pType<br />
where color = if (isUpper c) then White else Black<br />
pType = case (toUpper c) of<br />
'P' -> Pawn<br />
'N' -> Knight<br />
'B' -> Bishop<br />
'R' -> Rook<br />
'Q' -> Queen<br />
'K' -> King</p>
<p>addToBoard :: Piece -> Int -> Board -> Board<br />
addToBoard piece loc board = board // [(loc, piece)]<br />
</code></p>
<p>An empty board is trivially defined as an integer within the proper range, and with no associations. I'll note here that I've never really dealt with arrays in haskell, so this will be a learning process. I already like the fact that creating an empty array is so intuitive. The piece function is a simple constructor for Piece. It follows a typical chess convention for denoting pieces: uppercase means white, lowercase means black. More on chess notation in a moment. addToBoard adds a piece to the board. Again, it's very simple and elegant-feeling. </p>
<p>Now comes the fun part for this entry:<br />
<code><br />
loadFEN :: String -> Board<br />
loadFEN = loadFEN' 56 emptyBoard</p>
<p>loadFEN' :: Int -> Board -> String -> Board<br />
loadFEN' _ b (' ':xs) = b<br />
loadFEN' _ b "" = b<br />
loadFEN' n b ('/':xs) = loadFEN' (n-16) b xs<br />
loadFEN' n b (x:xs) | x `elem` ['1'..'9'] = loadFEN' (n + (digitToInt x)) b xs<br />
loadFEN' n b (x:xs) = loadFEN' (n+1) b' xs<br />
where b' = addBoard (piece x) n b<br />
</code></p>
<p>Chess has this awful thing about notation. There are a few different ones (particularly for move representation), and they tend to be pretty awful. This function is to convert a string, in a notation called FEN, to an instance of our board data structure. a description of FEN can be found <a href="http://en.wikipedia.org/wiki/Forsyth-Edwards_Notation">here</a> . Suffice it to say, this is a tedious process to do in any language. In fact, the above function is very elegant compared to many languages. Essentially, we're simply looping through the string, while keeping a reference to the next square on the board that we're going to put a piece on. Since FEN starts with the square on black's right, we start on square 56 (see above diagram). We'll assume for now that the FEN is well-formed. </p>
<p>If you notice from the Wikipedia article, there are several fields to FEN notation. For now, we'll just deal with the first, and longest field, which tells where the pieces are. We'll come back to the other fields later. Thus, if the first character of the string is a space, or if the string is empty, then we're done, and we can simply return the board. If it's a slash, we've reached the end of a row, and we need to move the board reference to the beginning of the next row, then process the rest of the string. If the first character is a digit, it indicates some empty squares, so we'll simply adjust the board reference again. Finally, the only option left, is that we're looking at an actual piece, in which case we need to construct the piece, add it to the board, and process the rest of the string. </p>
<p>I think that's enough for this entry. Next time: move generation!</p>
http://sequence.complete.org/node/296#commentsApplicationsDiscussionThu, 28 Jun 2007 20:30:01 -0700chessguy296 at http://sequence.complete.orgI've seen the J and the C, how about the Haskell?
http://sequence.complete.org/node/269
Some swarthy Haskell'ing lad needs to step up to the plate on this one. How would Haskell do this? We simply want the column of the maximum value of the array.
<P>
<STRONG>C Language</STRONG>
<PRE>
int i, j, maxcol = 0;
float maxval = x[0][0];
for(i = 0;i<=xsize0;++i) {
for(j = 0;j<=xsize1;++j) {
if(x[i][j] > maxval) {
maxval = x[i][j];
maxcol = j;
}
}
}
</PRE>
<STRONG>J Language</STRONG>
<PRE>
maxcol =. (i. >./) >./ x
</PRE>
<P>
My that <a href="http://www.jsoftware.com">J</a> code is quite concise
... so now we need to see that <STRONG>H</STRONG> language ... heheh.http://sequence.complete.org/node/269#commentsApplicationsFri, 30 Mar 2007 12:38:17 -0700metaperl269 at http://sequence.complete.orgMy recent Factor travels in Light of Haskell
http://sequence.complete.org/node/264
<p><a href="http://www.FactorCode.org">Factor</a> is a modern stack-based language. It has a very interactive and easy-to-use GUI and is fun to work with.</p>
<p>Something was itching me about using this language and it was not until I picked up <a href="http://homepages.cwi.nl/~jve/HR" />Haskell Road to Logic Maths and Computer Programming</a> that I knew what was bothering me. He says that _Haskell_ is a type of descriptive programming very different from the prescriptive programming that you see in Java or C.</p>
<p>And that's it. In Factor, one is very mechanical. putting things on the stack, duplicating stack items. Hiding things in a retain stack, etc. </p>
<p>I notice that a lot of Factor functions for stack shuffling scale up to 3 stack elements. Is there something magic about this number of args to a word that it would never have to shuffle on more?</p>
<p>A very telling example of the difference in Haskell and Factor has to do with<br />
<a href="http://www.factorcode.org/responder/browser/?word=all?&vocab=sequences">this page on the Factor website</a> discussing how to determine if all elements of a sequence obey a boolean:</p>
<blockquote><p>
The word "all"<br />
Tests if all elements in the sequence satisfy the predicate.</p>
<p>The implementation makes use of a well-known logical identity:</p>
<p>P[x] for all x <==> not ((not P[x]) for some x)</p></blockquote>
<p>Let's compare the Factor and the Haskell:</p>
<p><EM>Factor</EM></p>
<pre>
: all? ( seq quot -- ? )
swap [ swap call not ] contains-with? not
</pre><p>
<EM>Haskell</EM></p>
<pre>
all p = and . map p
</pre><p>
<strong>conclusions</strong></p>
<p>The author of Factor is a very strong mathematician... what provoked him to involve himself in stackrobatics (acrobatics with a stack)?</p>
http://sequence.complete.org/node/264#commentsApplicationsSat, 24 Feb 2007 01:46:31 -0800metaperl264 at http://sequence.complete.orgHaskell Factor again
http://sequence.complete.org/node/262
<p><EM>HaskelL</EM><br />
<code><br />
map putStrLn $<br />
map (\(a,b) -> "Index: " ++ (show b) ++ "element: " ++ a) ( zip ["a" , "b", "c"] [0..] )</p>
<p></code></p>
<p><em>Factor</em></p>
<p><code><br />
{ "a" "b" "c" } dup length [ "Index: " write . "Element: " write . ] 2each</p>
<p></code></p>
<p><STRONG>CONCLUSION</STRONG></p>
<p>Draw your own conclusions :)</p>
http://sequence.complete.org/node/262#commentsApplicationsThu, 01 Feb 2007 11:55:52 -0800metaperl262 at http://sequence.complete.orgFactor and Haskell comparison
http://sequence.complete.org/node/261
<p><STRONG>Haskell</STRONG><br />
<CODE><br />
let sq = (\x -> x * x) in map sq $ map sq [1 .. 3]<br />
</CODE></p>
<p><STRONG>Factor</STRONG><br />
<CODE><br />
{ 1 2 3 } [ sq ] map [ sq ] map .<br />
</CODE></p>
<p><STRONG>Haskell 2</STRONG><br />
<CODE><br />
let sq = (\x -> x*x) in map (sq . sq) [1..3]<br />
</CODE></p>
<p><STRONG>Factor 2</STRONG><br />
<CODE><br />
{ 1 2 3 } [ sq sq ] map .<br />
</CODE></p>
<p><STRONG>Factor 3</STRONG><br />
<CODE><br />
3 [ 1+ sq sq ] map .<br />
</CODE></p>
<p><EM>CONCLUSION</EM></p>
<p>One interesting thing is that no new language mechanisms were necessary in Factor. In Haskell, one had to know <code>$</code> and the composition operator <code> . </code> as well a varioius precedence rules to make clean concise code.</p>
http://sequence.complete.org/node/261#commentsApplicationsThu, 01 Feb 2007 09:23:45 -0800metaperl261 at http://sequence.complete.orgHaskell Xcode Plugin
http://sequence.complete.org/node/254
<p>Thanks to Damien Bobillot for writing the <a href="http://maxao.free.fr/xcode-ocaml-plugin/">Objective Caml plugin</a>, and his efforts in researching the <a href="http://maxao.free.fr/xcode-plugin-interface/">Xcode plugin API interface</a>, I've written in the last week, an <a href="http://www.hoovy.org/HaskellXcodePlugin/">Xcode plugin for Haskell</a>. </p>
<p>Thanks to everyone for their direct and indirect support.</p>
http://sequence.complete.org/node/254#commentsApplicationsRelease AnnouncementsMon, 08 Jan 2007 12:46:02 -0800humasect254 at http://sequence.complete.org