简体   繁体   中英

How to generalize input in Haskell

I am just starting to learn Haskell and I am using learnyouahaskell.com as the guide, and I am using ghci as interpreter. I have a question regarding lists. On the website they specify the function:

boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]

This works only for lists. Whereas

boomBangs x = [ if x < 10 then "BOOM!" else "BANG!" | odd x]

Only works for single inputs, ie

boomBangs 21
boomBangs 7

Is there a way to write this statement so that it doesn't matter whether I put

boomBangs [2,5,6,7,1]

or

boomBangs 7

without the need of an if statement?

In general, Haskell does not allow you to just arbitrarily overload the same function name with multiple distinct implementations. There are programming languages that let you do this; Haskell is not one of them.

In general, if you want the same function to do something different for different types of arguments (or different return type, for that matter), you use type classes. However, even this does not allow you to just arbitrarily have different numbers or types of arguments; there must be a pattern to it.

I realise this is only for experimentation purposes, but I second the comment by dfeuer: what is boomBangs supposed to mean ? What argument types does it make sense for? Well, obviously in this case boomBangs is a trivial example function, and doesn't really make much sense for anything except as an example function. (I'm not sure if you've even got to the type class part of the tutorial yet.)

Notice that, as written, boomBangs is already polymorphic: It will work for any type of integer. It works for signed 8-bit integers, unsigned 8-bit integers, signed 16-bit integers, unsigned 16-bit integers, arbitrary-precision integers... So it's working for quite a bit of stuff.

Making it work for lists and non-lists isn't a very natural generalisation of this function. (It is boom-bang , after all.) What might make sense is to generalise it to work for other foldable objects (eg, list, Maybe , Either e ). 毕竟。)什么可能是有意义的是推广它为其他可折叠的对象(例如,列表,工作MaybeEither e )。 It might also make sense for it to work on any monad (eg, it looks like a slight tweak of this might work for stateful computations or parsers or I/O actions). But again, I don't know if either of those concepts have been introduced in the tutorial yet.

Yes. Name your second function differently: boomBang . Then write boomBangs [2,5,6,7,1] or boomBang 7 -- no if required.

Writing code should be easy and natural, don't make it harder on yourself than it has to be.

Now you have

boomBangs xs = [b | x <- xs, b <- boomBang x]

removing the code duplication, which is usually a sign of underexplored problem space.

You may implement different behaviors for different types using type classes. For example:

class BoomBang a where
    boomBang :: a -> [String]

instance BoomBang Integer where
    boomBang x = [if x < 10 then "BOOM" else "BANG" | odd x]

instance BoomBang a => BoomBang [a] where
    boomBang xs = xs >>= boomBang

In ghci:

> boomBang 7
["BOOM"]
> boomBang [2,5,6,7,1]
["BOOM","BOOM","BOOM"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM