• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Haskell

Status
Not open for further replies.
Level 6
Joined
Aug 26, 2009
Messages
192
You decide to use functional languages because you prefer it, not because of speed.

If you ONLY want speed you will code Assembler, C or C++.

Actually counts for all programming languages. I decide to use Java not because of the speed, because it's easyer to work with Java instead of C or C++. Speed is NEVER the only aspect of a programming language.
 
You decide to use functional languages because you prefer it, not because of speed.

If you ONLY want speed you will code Assembler, C or C++.

Actualy you use them if you want good speed for easy implementation, this is specialy the case of parallizeable code. Because of function purity, making the code be parallizeable is a lot easier.
 

Ralle

Owner
Level 77
Joined
Oct 6, 2004
Messages
10,101
Actualy you use them if you want good speed for easy implementation, this is specialy the case of parallizeable code. Because of function purity, making the code be parallizeable is a lot easier.
Good point.

Well Rui. If you want pure speed and you know what you're doing, you can get the best speeds with C or C++ unless you are super pro / crazy and write everything in Assembler.
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
But isn't Assembly different for distinct processor architectures? If I wrote something in Assembly wouldn't I have to write distinct code for distinct machines?

By the way, I've got to deliver my first Programming Principles task next week and I wanted to make sure everything's okay. Does this function do what I think it does? Won't it block on generating the list?

Code:
evenDivisors n = take (n/2) [ x | x <- [2,4..], n 'mod' x == 0 ]

EDIT: GW suggestion
evenDivisors n = take (div n 2) [ x | x <- [2,4..], mod n x == 0 ]
 
Last edited:

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
Supposedly, Haskell will only generate a list that has as many elements as take() requires, instead of generating that endless list. Having no take function will actually make the generation infinite.

P.S. — I didn't use [2,4..n] because I think it'll yell at you if n < 4, and n should be a natural number.

P.P.S. — Isn't there a function that allows me to round up the value of take()? I think it'll crash if it receives a float instead of the expected int.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
n / 2 is an error, since the division operator isn't defined for Integral types.
Use the div function.

In addition, I was right about the need for a bound since given an input with no even divisors, you will go to infinity and beyond (this also means you can drop the take).
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Bind it = give it a name you can reference it with.

Though in JavaScript and Lua "_" is a legal variable name you can reference, so I wouldn't be surprised if it's the same way in Haskell.
People just use it to show that they don't care about that specific value.

E.g. in a function that checks the length of a list by iterating over it, you really don't care about the list elements, only the number of iterations, so you'd use _ instead of a meaningful name.
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
Assembler is for slowpokes, GPU parallelism is the way to go! (this is both a joke and reality, and a joke on reality, and a joke on YOU, because who gives a damn about speed (no DSG, don't start it here too)).

Can you please stop bullshitting interesting threads with your gpu shit? Its unrelated but even if this was a gpu computing thread it would still be boring.

Functional languages are VERY interesting for parallelism because its functions are stateless (unlike functions in imperative languages). That means the result of a function depends only on its arguments and not on the time or order which it is executed in.

However what GPUs do is very simple SIMD parallelism which covers only a very small part of parallel computing. Also its boring, BORING AS FUCK.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
It's just an IDE(codeblocks). I've never tried haskell but it looks good. What do you need to run haskell codes? I mean does it need something like java (JRE)? Anyways, thanks.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Thanks, I also found some online interpreters, looks cool, trying the beginner tutorials, thanks Rui. :D
 
Level 6
Joined
Aug 26, 2009
Messages
192
Tail-recursion means, that the last statement is only the recursive call. Usually the interpreter/compiler makes a normal loop out of it and you don't need that much space on the stack for all the function calls. Example:
func fak(n)
if n <= 1 return 1
else return n * fak(n-1)

this isn't tail recursion since the last statement (n * fak(n-1)) also includes the multiplication. To prevent this you can do it like this:

func fak(n)
return fak-rek(n, 1)

func fak-rek(n, res)
if n <= 1 return res
else return fak-rek(n - 1, res * n)
 
Well pretty much tail-recursion means that all recursive calls are at the end of a function's execution path and that are undependant of any operation in that executation path.

Examples of factorial in haskell:
Code:
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * (factorial n-1)

-- tail recursive
factorial :: Int -> Int
factorial 0 = 1
factorial n = factorialAux n 1
    where
        factorialAux 1 v = v
        factorialAux n v = factorialAux (n-1) (v*n)

As you see, i just pass the result as an argument, this way I can make sure the tail recursive property is kept. The compiler will optimize that into a simple fast loop, rather than a recursive function. If you look at the tail recursive call, the current argument frame is no longer needed, therefore the space used for them can be recycled instead of creating a new frame in the stack.

Here's how it would look using prelude functions
Code:
-- using prelude functions
factorial :: Int -> Int
factorial 0 = 1
factorial n = product [1..n]

the reason why it's good practice to use prelude functions and high order functions in haskell, has to do with the fact that all prelude functions are very optimized for the task. It also has to do with some compiler optimizations.
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
Hey, nice that you're here BlinkBoy, I'm having some trouble with this:

Code:
foldMatrizParaLista xs = nub . ( foldr (\y acc -> (fst(y)):acc) [] xs )

Basically, the function is supposed to take a list of tuples and build another list with only the first element of each tuple, eliminating repetitions, of course. The compiler says this:

PHP:
Couldn't match expected type `a -> [a1]' with actual type `[a2]'
Relevant bindings include
foldMatrizParaLista :: [(a2, b)] -> a -> [a1]
(bound at

I've got a much easier way to do this, but we were ordered to resort to foldl/r.
 

peq

peq

Level 6
Joined
May 13, 2007
Messages
171
Hey, nice that you're here BlinkBoy, I'm having some trouble with this:

Code:
foldMatrizParaLista xs = nub . ( foldr (\y acc -> (fst(y)):acc) [] xs )

Basically, the function is supposed to take a list of tuples and build another list with only the first element of each tuple, eliminating repetitions, of course. The compiler says this:

PHP:
Couldn't match expected type `a -> [a1]' with actual type `[a2]'
Relevant bindings include
foldMatrizParaLista :: [(a2, b)] -> a -> [a1]
(bound at

I've got a much easier way to do this, but we were ordered to resort to foldl/r.

The use of the dot is the problem. The dot is function composition, so it expects a function on the right hand side of the dot (expected type `a -> [a1]'), but you give it a list instead (actual type `[a2]').

You could remove the dot or remove the last argument:

Code:
foldMatrizParaLista1 :: Eq a => [(a,b)] -> [a]
foldMatrizParaLista1 xs = nub (foldr (\y acc -> (fst y):acc) [] xs)

foldMatrizParaLista2 :: Eq a => [(a,b)] -> [a]
foldMatrizParaLista2 = nub . (foldr (\y acc -> (fst y):acc) [])

foldMatrizParaLista3 :: Eq a => [(a,b)] -> [a]
foldMatrizParaLista3 = nub . (foldr ((:) . fst) [])

foldMatrizParaLista4 :: Eq a => [(a,b)] -> [a]
foldMatrizParaLista4 = nub . (map fst)
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
Duh, I placed that dot because my initial idea was different, then I forgot to remove it. Then compilers could actually be a little more friendly. If someone ever makes a compiler in 1 programming language that actually tells you what's wrong with your script... T.T

Thanks so much!

EDIT: Hold on, are you sure the dot in the second function is gonna work?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
codeblocks, visual studio, GCC and many more will say whats wrong with the script and also the line the error is in
however I think neither of those support(maybe GCC, it supports even brainfuck) Haskel
while GCC is mostly for linux(MinGW has windows version of it) linux, it will say in console even possition of not matching character
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
I have another problem. Usually, the '$' sign appears inbetween parameters, but I have no idea how to do it in this case. I want the arguments taken to be associated to f.
Right now it yells at me because of it thinks I'm associating more arguments to length and not passing the arguments to f, which takes the same types as g.
Code:
g = length f

Every variation I've tried returns an error as well:
Code:
g $ = length f  -- Input error '='
g = length $ f
g = $ length f  -- Parse error input '$'

This is to make use of currying and avoid the following:
Code:
g xs x = length ( f xs x )     -- Eliminating those xs and x on both sides makes the function that much cleaner
 

peq

peq

Level 6
Joined
May 13, 2007
Messages
171
Do not get too obsessed with point free style ;) It can get quite unreadable sometimes. For example here you could probably use this:

Code:
g = ((.) . (.)) length f

But who wants to read that?

And the $ operator is really useless as (f x) means the same as (f $ x). It is only used to avoid parenthesis.
 
Do not get too obsessed with point free style ;) It can get quite unreadable sometimes. For example here you could probably use this:

Code:
g = ((.) . (.)) length f

But who wants to read that?

And the $ operator is really useless as (f x) means the same as (f $ x). It is only used to avoid parenthesis.

Well I use $ a lot to make my code more readable sometimes.

the eager operator $! on the other hand is quite more usefull.
 

peq

peq

Level 6
Joined
May 13, 2007
Messages
171
Could somebody explain to me what that ((.) . (.)) does though?

So (.) is the function composition operator. It is defined like this:

Code:
(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

So (f . g) x is the same as (f (g x)).

Knowing this you can rewrite the expression ((.).(.)) as follows:

Code:
((.) . (.))
-- remove infix notation
((.) (.) (.))
-- replace (.) with its definition
((\f g x -> f (g x)) (\f g x -> f (g x)) (\f g x -> f (g x)))
-- rename variables
((\f1 g1 x1 -> f1 (g1 x1)) (\f2 g2 x2 -> f2 (g2 x2)) (\f3 g3 x3 -> f3 (g3 x3)))
-- inline parameter f1
(\g1 x1 -> (\f2 g2 x2 -> f2 (g2 x2)) (g1 x1))  (\f3 g3 x3 -> f3 (g3 x3))
-- inline parameter g1
(\x1 -> (\f2 g2 x2 -> f2 (g2 x2)) ((\f3 g3 x3 -> f3 (g3 x3)) x1))
-- inline parameter f3
(\x1 -> (\f2 g2 x2 -> f2 (g2 x2)) (\g3 x3 -> x1 (g3 x3)))
-- inline parameter f2
(\x1 -> (\g2 x2 -> (\g3 x3 -> x1 (g3 x3)) (g2 x2)))
-- inline parameter g3
(\x1 -> (\g2 x2 -> (\x3 -> x1 (g2 x2 x3))))
-- rewrite lambda
(\x1 g2 x2 -> (\x3 -> x1 (g2 x2 x3)))
-- rewrite lambda
(\x1 g2 x2 x3 -> (x1 (g2 x2 x3)))
-- rewrite lambda
(\x1 g2 x2 x3 -> x1 (g2 x2 x3))
-- rename parameters
(\f g x y -> f (g x y))

I think the last expression is a bit clearer.
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
I'm having a new problem. The following function f is correct, but Haskell doesn't appear to like the signature (I've put it as a comment)?

I'm still trying to understand what's the order of evaluation of ((.) . (.)) though =s

Code:
suc :: Eq a => [(a,a)] -> a -> [a]
adj :: Eq a => [(a,a)] -> [a]

--f :: Eq a => [(a,a)] -> [(a,[a])]
f graph = [ (x,y) | x <- (adj graph) , y <- ( suc graph x ) ]
 

Rui

Rui

Level 41
Joined
Jan 7, 2005
Messages
7,550
Shouldn't the range iterate through each possible x and y? Actually the y is really supposed to be a list, now I'm in doubt how to do that. I want every pair to have one of each x of the list and y to be the list that comes from suc.

Blink, you can't explain the order of evaluation of ((.) . (.))? I'm really curious about that, the demonstration is weird, I don't quite follow from the first inline onwards. peq? >< Where did you learn this trick?
 

fladdermasken

Off-Topic Moderator
Level 39
Joined
Dec 27, 2006
Messages
3,688
Yay, this thread is still running!
Hmm $! doesn't appear on Learn You A Haskell for Great Good!, I guess I have to search elsewhere?
It's defined in terms of seq.

f $! x = x seq f x

seq is the simplest way to introduce strictness to your program. seq takes two arguments of any type and returns the second. It's also magically strict in its first argument. So,
⊥ `seq` b = ⊥
a `seq` b = b

Basically x `seq` y will evaluate x before it considers y.

You can use ($!) pretty much like you do the ordinary function application operator.
f x = g $! h $! x

which will evaluate x, h x and apply g to the result, in that order. If you want to read more, there should be plenty of info on the Haskell wiki.
 

peq

peq

Level 6
Joined
May 13, 2007
Messages
171
Blink, you can't explain the order of evaluation of ((.) . (.))?

The order usually does not matter in Haskell since there are no side-effects. So you can usually evaluate a Haskell expression as you would simplify a mathematical expression.

I'm really curious about that, the demonstration is weird, I don't quite follow from the first inline onwards. peq? >< Where did you learn this trick?

I have seen it here: http://stackoverflow.com/questions/5821089/haskell-function-composition-operator-of-type-cd-abc-abd

Maybe you could also write it as "(length .) . f", which is a bit more readable, but I still would not write something like that.

I don't know how to explain it any better than in my last post and I don't think there is a way to read this nicely. That's why it should not be used ;)

One problem with Haskell is that people actually use stuff like this which makes some code very hard to read, if you have not seen a certain operator or pattern.
 
Status
Not open for further replies.
Top