[Haskell-beginners] Case vs Guards. I still don't know what is the difference
Semih Masat
masat.semih at gmail.com
Thu Jul 7 09:21:40 UTC 2016
Thank you Theodore and Tushar.
Great examples and help.
I am understanding better now.
On Thu, Jul 7, 2016 at 5:12 AM, Tushar Tyagi <tushar4r at gmail.com> wrote:
> It's great that you understood that the idiom of using case expressions is
> with pattern matching -- using it to count numbers is like using a crane to
> pick a packet of sugar -- pretty inefficient.
>
> The case expression/pattern matching is very powerful and expressive. And
> I will be using a single example for multiple definitions (which you
> advised against), hoping that you see the difference between different
> idioms.
>
> Take a look at the definition of map below:
>
> map' f xs = case xs of
> [] -> []
> (y:ys) -> f y : map' f ys
>
> Without pattern matching you will be using library functions like `null`,
> `head`, or `tail` and one of the downsides of these is that they crash the
> program in case `head` and `tail` are used with empty list without null
> checking. With the null check, the program looks inelegant (and is not the
> standard idiom):
>
> map'' f xs = if null xs
> then []
> else let hd = head xs
> tl = tail xs in
> (f hd) : (map'' f tl)
>
> You can clearly see the superior one.
>
> Of course, pattern matching is not used only with case expressions: here
> is the definition of drop with and without case:
>
> drop'' n xs = case (n, xs) of
> (0, xs) -> xs
> (_, []) -> []
> (n, y:ys) -> drop'' (n-1) ys
>
> drop' 0 xs = xs
> drop' _ [] = []
> drop' n (x:xs) = drop' (n-1) xs
>
> In my opinion, the second one without the case expression is clearer.
>
> One more use case of case expression (and pattern matching) is when you
> start creating your own datatypes. Then you can destructure the type and
> add the required logic based on the type:
>
> data MyType a b = TypeA a | TypeB b
> deriving (Show)
>
> which_type a = case a of
> TypeA a -> "Type A" -- Or some better logic here.
> TypeB b -> "Type B"
>
> Hope this makes things a bit clearer.
>
>
> On Thu, Jul 7, 2016 at 6:46 AM, Semih Masat <masat.semih at gmail.com> wrote:
>
>> Sorry, if i am flooding.
>>
>> To make it clear what i wanted to say in last section on previous mail.
>>
>>
>>
>> Lets say i have a list of numbers and i want to do different things in
>> case of different even numbers on that list.
>>
>> If i use guards i will do it like this :
>>
>> nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
>> howManyEvens = length(removeOdd(nums))
>>
>> isItOk count
>> | count > 10 = "Too much"
>> | count > 8 = "Isn't this a little much?"
>> | count > 5 = "I think this is ok"
>> | count > 3 = "Little more please"
>> | count > 0 = "Ooo, cmon"
>> | otherwise = "We gonna die"
>>
>> result = isItOk howManyEvens
>>
>> This is a very stupid example but this will work i guess.
>>
>> And if i wanted to this with *case* , i will do it like;
>>
>> isItOk' nums = case (length(removeOdd(nums))) of
>> 10 -> "Too much"
>> 8 -> "Isn't this a little much?"
>> 5 -> "I think this is ok"
>> 3 -> "Little more please"
>> 0 -> "Ooo, cmon"
>> x -> "i don't even"
>>
>> So the only different thing is i didn't need to create *howManyEvens*
>> constant.
>>
>>
>> PS: While i writing this. I realized that with case, i need to use
>> pattern matching but with guards i can use other functions if i wanted to.
>> ( like count > 10 )
>> Sorry for asking prematurely. And if anyone reaches this email by google
>> search. Look at this explanation : http://stackoverflow.com/a/4156831
>>
>> To the authors : Please, if you writing a book a blog post about haskell.
>> Don't create same function in different styles. We don't understand which
>> one we need to use and why we have all different choices.
>>
>> Thanks.
>> Semih
>>
>> On Thu, Jul 7, 2016 at 3:43 AM, Semih Masat <masat.semih at gmail.com>
>> wrote:
>>
>>> Hello,
>>>
>>> I am new to Haskell and trying to learn it with learnyouahaskell.com
>>> and Pluralsight Haskell course.
>>>
>>> And i have a very noob question.
>>>
>>> I understand that *if .. else* is just a syntactic sugar over *case. *But
>>> what about guards then ?
>>>
>>> Are guards also *case *in different syntax ? Or vice versa ? Like with
>>> an example.
>>>
>>>
>>> anyEven nums
>>> | (length (removeOdd nums)) > 0 = True
>>> | otherwise = False
>>>
>>>
>>> anyEven' nums = case (removeOdd nums) of
>>> [] -> False
>>> (x:xs) -> True
>>>
>>> I can do the same thing with both of them.
>>>
>>> As i understand the only different thing is, with *case *i can
>>> manipulate the parameter (like here in the example i used removeOdd) and
>>> can use the manipulated parameter to decide what to do after that.
>>> So i will not need to use removeOdd function inside the case. ( maybe i
>>> will need to use in every guard definition if i choose to use guards )
>>>
>>> Is this it?
>>>
>>> Is this the only difference between them ?
>>>
>>> And if it is, why haskell needed do implement both of them. Can't we use
>>> function like removeOdd before using it on case or guard functions ?
>>>
>>>
>>> Thanks, and sorry if my english is bad.
>>>
>>> Semih Masat
>>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20160707/590b594b/attachment-0001.html>
More information about the Beginners
mailing list