Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 22nd, 2006, 1:21 PM   #1
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Haskell

Does anyone have any experience with Haskell?

I've been trying to learn the language (based on the principle that if you can learn Haskell, you can learn anything), and I've been writing a number of small programs to help me learn.

One of the programs is a module that implements a bag data structure (similar to a set, but keeps track of the amounts of each item). I've been trying to construct a function to give me a sub-bag of the N most common elements, but I have yet to have much luck. Here's what I have so far:
module Bag where

import Data.Map as Map

type Bag a = Map a Int

fromList :: Ord a => [a] -> Bag a
fromList []     = Map.empty
fromList (x:xs) = Map.insertWith (+) x 1 (Bag.fromList xs)

mostCommon :: Int -> Bag a -> Bag a
{- How to implement this function ... -}
Arevos is offline   Reply With Quote
Old Jul 28th, 2006, 12:47 PM   #2
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
For those interested, here's a working (if limited) bag module:
module Bag where
import Data.Map as Map
import List

-- A bag is a specialised type of map
type Bag a = Map a Int

-- Creates a bag from a list
fromList :: Ord a => [a] -> Bag a
fromList []     = Map.empty
fromList (x:xs) = Map.insertWith (+) x 1 (Bag.fromList xs)

-- Compares the latter value of two tuples
compareAmounts :: Ord b => (a,b) -> (a,b) -> Ordering
compareAmounts (_,x) (_,y) = compare x y

-- Creates an ordered list from a bag
toAscList :: Ord a => Bag a -> [(a, Int)]
toAscList = (sortBy compareAmounts) . Map.toList

-- Returns the most common elements in the bag
mostCommon :: Ord a => Int -> Bag a -> Bag a
mostCommon n = Map.fromList . (Map.foldWithKey maximumValues [])
	where maximumValues k v maxs = take n (insertValues k v maxs)
	      insertValues  k v      = insertBy (flip compareAmounts) (k,v)
Haskell's a rather interesting language. If you can wrap your head around it, I'd advise learning it. It's sufficiently different from most other languages to introduce you to some intriguing concepts.
Arevos is offline   Reply With Quote
Old Jul 30th, 2006, 2:05 PM   #3
Yegg
Newbie
 
Join Date: Jan 2006
Posts: 20
Rep Power: 0 Yegg is on a distinguished road
Clean (http://www.cs.ru.nl/%7Eclean/index.html) is also an interesting language to check out, I was learning this for a while, it's based on Haskell for the most part but adds other functional programming concepts including some features not found in other languages.
Yegg is offline   Reply With Quote
Old Dec 11th, 2006, 9:29 PM   #4
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 641
Rep Power: 4 Jessehk is on a distinguished road
Arevos, I've been bored lately so I took up your challenge. This is the beginnings of a card module I wrote after reading for about 3-4 hours. At this point, I don't really understand monads, but I think I'm doing the random stuff correctly.

Cards.hs
-- Written by Jessehk on
-- Monday December 11, 2006

module Cards
    where

import System.Random

data Card = Card Face Suit
          | Joker
          deriving (Show, Eq)

data Suit = Hearts
          | Diamonds
          | Clubs 
          | Spades
          deriving (Show, Eq)

suits :: [Suit]
suits = [Hearts, Diamonds, Clubs, Spades]

data Face = Jack
          | Queen
          | King
          | Ace
          | Number Int
          deriving (Show, Eq)

faces :: [Face]
faces = [Number 2 , Number 3, Number 4, Number 5,
         Number 6 , Number 7, Number 8, Number 9,
         Number 10, Jack    , Queen   , King    ,
         Ace]

-- Return a list of all cards of a given Suit.
allOfSuit :: Suit -> [Card]
allOfSuit = cardsFromList . (zip faces) . repeat

deck :: [Card]
deck = (concat . map allOfSuit) suits

-- Return a List of cards from a List of tuples.
cardsFromList :: [(Face, Suit)] -> [Card]
cardsFromList []                  = []
cardsFromList ((face, suit) : xs) = Card face suit : cardsFromList xs

shuffle :: [Card] -> IO [Card]
shuffle []    = return []
shuffle cards = do
    card <- randCard cards
    rest <- shuffle $ filter (/= card) cards
    return (card : rest)

randCard :: [Card] -> IO Card
randCard cards = do
    numb <- randomRIO (0 :: Int, length cards - 1)
    return $ cards !! numb

Main.hs
module Main
    where

import Cards

main = do
    shuffled <- shuffle deck
    (putStrLn . show . length) shuffled
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!

Last edited by Jessehk; Dec 11th, 2006 at 10:29 PM.
Jessehk is offline   Reply With Quote
Old Dec 12th, 2006, 3:50 AM   #5
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Jessehk View Post
Arevos, I've been bored lately so I took up your challenge. This is the beginnings of a card module I wrote after reading for about 3-4 hours.
It's not half bad - I'm especially impressed with your use of the IO monad. I had all sorts of problems with that.

Quote:
Originally Posted by Jessehk View Post
At this point, I don't really understand monads, but I think I'm doing the random stuff correctly.
Monads puzzled me for an age, because most of the articles explaining them deal with very generic concepts, and I found it difficult to pin down their use. The article that made everything click was You Could Have Invented Monads! (And Maybe You Already Have.), so I thoroughly recommend reading it. The You-Could-Have article demonstrates monads from first principles, leading you through a variety of problems, and then pointing out that the answers you come up with all have a common thread.

I found monads are tricky not because they're inherently complex, but because they're such a generic concept it's difficult to relate them back to practical problems. The You-Could-Have article neatly bridges that gap, I discovered.
Arevos is offline   Reply With Quote
Old Dec 13th, 2006, 2:01 PM   #6
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 641
Rep Power: 4 Jessehk is on a distinguished road
Thanks for the article, I'll have a look.

Haskell is interesting, but any idea that somebody with not a lot of programming experience could learn on Haskell is just wrong (IMO). For a start, the standard library documentation is very unforgiving (very little hand-holding).
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!
Jessehk is offline   Reply With Quote
Old Dec 13th, 2006, 2:33 PM   #7
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
You may be correct; I'm certainly having to do some mental adjustment. In the absence of documentation, you're certainly right.

On the other hand, learning to solve problems without the overhead of preconceptions coming from non-functional languages may make learning from scratch no more difficult than learning to solve problems using other languages. Low level procedural languages are certainly not a good match for our natural, more abstract mental processes.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Dec 13th, 2006, 4:24 PM   #8
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Jessehk View Post
Haskell is interesting, but any idea that somebody with not a lot of programming experience could learn on Haskell is just wrong (IMO). For a start, the standard library documentation is very unforgiving (very little hand-holding).
Yeah, that's my impression too; it's certainly not for beginners. Though that's why Haskell interests me, because it's a very difficult language to get to grips with. There are a lot of very abstract concepts in Haskell, and every so often I find myself looking at previous functions I've written and realising that there are better ways to achieve the same thing.

For instance, previously, I wrote a mostCommon function using standard functional techniques, such as fold and filter. However, now I can't help wondering if I couldn't create a simpler, more abstract function by making use of all the functions in Haskell that operate upon monads. I'll try and see if it's possible to come up with something better.

I think the attraction of Haskell is not so much that it is functional, but because it enables developers to play around with very abstract concepts in a way other languages can't easily match. It's my opinion that a lot of what makes a good programmer good is his or her ability to think abstractly about a problem. For instance, a beginner who wanted to calculate the first 10 fibonacci numbers might do something like this:
def fib(n):
    a = 1
    b = 1
    print a
    print b
    for i in range(n):
        c = a + b
        a = b
        b = c
        print b

fib(10)
A more adept programmer might do something like this:
def fib(n):
    s = [1, 1]
    for i in xrange(n):
        s.append(sum(s))
        yield s.pop(0)

for x in fib(10): print x
And abstracting it further still:
fib = 1 : 1 : zipWith (+) fib (tail fib)

main = mapM (putStrLn . show) (take 10 fib)
Each step abstracts the solution further, starting with a function (one of the most simple abstractions), then moving onto a generator, and then an infinite lazy sequence. Haskell is certainly geared more toward the higher abstraction, rather than ease of use
Arevos is offline   Reply With Quote
Old Dec 13th, 2006, 5:16 PM   #9
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
To me, the recursion seems somewhat natural. The idea that you can apply a function to something that reapplies it after making a step variation by some means seems neat. I'm still very raw with it, but I'm thinking of applying it to the tic tac toe game, as a learning exercise. Because the number of possible moves (especially when reduced by the idea of equivalence) is not terribly large, the lazy sequence wouldn't be infinite, but would terminate after nine moves or when a win or draw was detected. No pruning, ala chess, should be necessary -- the end should be reachable without resorting to pruning. This means that the outcome is a distinct value, and not a guess or approximation based on some set of evaluation rules. This thing of highly modular functions that can be composed into more complex functions, applicable to varying types, is just intriguing to me. I haven't messed with Lisp since the early 90s, but the notion of the Haskell list is distinctly familiar.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Dec 13th, 2006, 6:13 PM   #10
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by DaWei View Post
To me, the recursion seems somewhat natural. The idea that you can apply a function to something that reapplies it after making a step variation by some means seems neat.
I'm used to recursion in functions, but using recursion to definite an infinite sequence seems rather odd, somehow. Elegant and precise, certainly, but still a little unusual.
Arevos is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:31 PM.

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