Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   Other Programming Languages (http://www.programmingforums.org/forum38.html)
-   -   Haskell (http://www.programmingforums.org/showthread.php?t=10805)

Arevos Jul 22nd, 2006 2:21 PM

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 Jul 28th, 2006 1:47 PM

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.

Yegg Jul 30th, 2006 3:05 PM

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.

Jessehk Dec 11th, 2006 10:29 PM

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


Arevos Dec 12th, 2006 4:50 AM

Quote:

Originally Posted by Jessehk (Post 121050)
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 (Post 121050)
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.

Jessehk Dec 13th, 2006 3:01 PM

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).

DaWei Dec 13th, 2006 3:33 PM

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.

Arevos Dec 13th, 2006 5:24 PM

Quote:

Originally Posted by Jessehk (Post 121139)
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 :)

DaWei Dec 13th, 2006 6:16 PM

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.

Arevos Dec 13th, 2006 7:13 PM

Quote:

Originally Posted by DaWei (Post 121144)
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.


All times are GMT -5. The time now is 12:17 AM.

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