Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   Other Programming Languages (http://www.programmingforums.org/forum38.html)
-   -   Anyone with knowledge of Haskell? (http://www.programmingforums.org/showthread.php?t=11613)

BungalowBill Oct 17th, 2006 5:21 AM

Anyone with knowledge of Haskell?
 
Does anyone have any knowledge of using Haskell? I'm trying to write some functions to do some simple tasks.

For example, a program, getelem, which is given an integer n and a list, returns the nth element of the list. e.g.

Main> getelem 4 [1,2,3,4,5]
4

is what i hope the outcome would be. I understand there is a built in function !! that does this but i want to do it without using it. Can anyone offer any help?

Arevos Oct 17th, 2006 6:57 AM

My haskell isn't great, but you need to approach this problem from a recursive standpoint. Firstly, consider the limiting case; the set of arguments that will stop the recursion.

In this case, if n is 0, then all we have to do is return the beginning of the list (assuming that you want the first element to have an index of 0, rather than 1):
:

getelem 0 x:xs = x
So far so good? Now that the limiting case has been created, we want the general case. We want to define the general case in terms of itself, in a way that approaches the limiting case. So first, we want n to approach 0. Second, we want the list to be cut until the head of the list is the element we want. To put this in code:

:

getelem n x:xs = getelem (n - 1) xs

So your final function definition should look like:
:

getelem :: Integer -> [a] -> a
getelem 0 x:xs = x
getelem n x:xs = getelem (n - 1) xs

Note that I do not currently have access to a Haskell compiler, but hopefully my code should be syntaxically correct.

magnus.therning Oct 24th, 2006 4:29 AM

You need some parentheses around the list pattern:

:

getelem 0 (x:xs) = x
getelem n (x:xs) = getelem (n - 1) xs


By terminating on 0 you have made the function count elements from 0, rather than from 1 (as was suggested in the original post). I think starting from 0 is a better choice though :-)

BungalowBill Oct 24th, 2006 5:08 AM

Hi thanks for the replys and sorry i haven't replied. The site wouldn't let me log back in for some reason. I tried logging in about 4 times and each time i went to post, it asked me to log in again. Anyway i cracked that one i think thanks a lot.

I do have another question now though. How would i go about declaring a list? For example a list of tuples like ((Jane,Mary), (Scott,Brian)) which would mean that Jane likes Mary or Scott likes Brian for example. Which i could then use at the terminal like this.

Main> likes "Scott" "Brian"
True

Any clue?

Arevos Oct 24th, 2006 7:16 AM

Quote:

Originally Posted by magnus.therning
You need some parentheses around the list pattern

Whoops! You're quite correct!

Quote:

Originally Posted by BungalowBill
I do have another question now though. How would i go about declaring a list? For example a list of tuples like ((Jane,Mary), (Scott,Brian)) which would mean that Jane likes Mary or Scott likes Brian for example. Which i could then use at the terminal like this.

If I've understood you correctly, you want a hashtable of some kind. You can do this one of two ways. The most basic way is to define a list of tuples:
:

relationships = [("Jane", "Mary"), ("Scott", "Brian")]
And then to iterate through the entire list until you find a match. The long way of doing this would be:
:

inList :: Eq a => a -> [a] -> Bool
inList y (x:xs) = if y == x then True else (inList y xs)
inList y []    = False

likes a b xs = inList (a, b) xs

main = print (likes "Scott", "Brian", relationships)

Or you could do it using any:
:

likes a b xs = any (== (a, b)) xs
However, a more efficient way of doing this would be to use a set. As far as I'm aware, there isn't a standard set module for Haskell, but any decent Haskell implementation should have one in the standard library. For instance, GHC has Data.Set:
:

import Data.Set as Set

relationships = Set.fromList [("Jane", "Mary"), ("Scott", "Brian")]

likes a b s = Set.member (a, b) s

Because we're using a data type designed for this sort of work, the above allows for more efficient lookups than the standard iterative model.

BungalowBill Oct 24th, 2006 8:26 AM

Thats almost it but not quite.

I want to set up a list like you said with
:

relationships = [("Jane", "Mary"), ("Scott", "Brian")]

but at the terminal all i want to type is the name of the function, two strings and a true or false indicating whether or not they are in the same tuple.
Like:

Main> likes "Scott" "Brian"
True

and it has to be order sensitive. So:

>Main likes "Brian" "Scott"
False

gives false. I think its going to get really complicated

One possible solution that im thinking of would be this. From the potential liked person(2nd person), you first of all compute all the people that directly like them (the 1st people). If the potential liker is in the list, return True. Otherwise, call the function recursively to see if one of the (1st people) is liked by the potential liker. Combine the results for the different likers together. If you understand what i mean. Using || maybe.

I'm just confusing myself now. That ^^^ made sense when i thought of it but now im not too sure.

Arevos Oct 24th, 2006 8:48 AM

Uh, then how about:
:

likes a b = any (== (a, b)) relationships
Or
:

likes a b = Set.member (a, b) relationships
Almost exactly the same function, but this time the relationships list is hard coded. Is that what you wanted?

BungalowBill Oct 24th, 2006 12:04 PM

Yeah thanks that works great. For some reason i was thinking it was much more complicated that it was.

Now i'm attempting to create a noughts and crosses board.

I'll be back soon enough no doubt!

thanks.

BungalowBill Oct 26th, 2006 9:52 AM

Hi im back again. This time with another question on something i've already asked about.

if i was to set up another list called companies. Like:

companies = [("c1, "c2"), ("c3", "c1"), ("c4", "c3")]

where the first one in each list is the company that is owned. the second company in eachlist is the one that owns the first. SO eventually i should be about to prove that c2 owns c4 indirectly. (because c2 owns c1, c1 owns c3, c3 owns c4. So c2 must own c4 indirectly.

If i were to give haskell two companies. the owned one and the owner, how would i compute all the companies that directly or indirectly own the potential owned company?

magnus.therning Oct 26th, 2006 11:14 AM

Quote:

Originally Posted by BungalowBill (Post 117596)
Hi im back again. This time with another question on something i've already asked about.

if i was to set up another list called companies. Like:

companies = [("c1, "c2"), ("c3", "c1"), ("c4", "c3")]

where the first one in each list is the company that is owned. the second company in eachlist is the one that owns the first. SO eventually i should be about to prove that c2 owns c4 indirectly. (because c2 owns c1, c1 owns c3, c3 owns c4. So c2 must own c4 indirectly.

If i were to give haskell two companies. the owned one and the owner, how would i compute all the companies that directly or indirectly own the potential owned company?

I'm getting the distinct impression you are using this resource to get your home work done :-) I'm hoping for your sake you aren't and I don't think I'll bother with posting "full solutions" after this. This is my "solution":

:

ownPath2 :: [(String, String)] -> String -> String -> Maybe [(String, String)]
ownPath2 comps c1 c2 =
    let
        oP' [] _ = Nothing
        oP' ((d1, d2) : cs) s
            | s == d1 && c2 == d2 = Just [(d1, d2)]
            | s == d1 =
                case ownPath2 comps d2 c2 of
                    Just p -> Just ((d1, d2) : p)
                    Nothing -> oP' cs s
            | otherwise = oP' cs s
    in
        oP' comps c1



All times are GMT -5. The time now is 1:51 AM.

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