简体   繁体   中英

Capitalize Every Other Letter in a String — take / drop versus head / tail for Lists

I have spent the past afternoon or two poking at my computer as if I had never seen one before. Today's topic Lists


The exercise is to take a string and capitalize every other letter . I did not get very far...

Let's take a list x = String.toList "abcde" and try to analyze it. If we add the results of take 1 and drop 1 we get back the original list

> x = String.toList "abcde"
['a','b','c','d','e'] : List Char
> (List.take 1 x) ++ (List.drop 1 x)
['a','b','c','d','e'] : List Char

I thought head and tail did the same thing, but I get a big error message:

> [List.head x] ++ (List.tail x)
==================================== ERRORS ====================================

-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm

The right argument of (++) is causing a type mismatch.

7│   [List.head x] ++ (List.tail x)
                       ^^^^^^^^^^^
(++) is expecting the right argument to be a:

    List (Maybe Char)

But the right argument is:

    Maybe (List Char)

Hint: I always figure out the type of the left argument first and if it is
acceptable on its own, I assume it is "correct" in subsequent checks. So the
problem may actually be in how the left and right arguments interact.

The error message tells me a lot of what's wrong. Not 100% sure how I would fix it. The list joining operator ++ is expecting [Maybe Char] and instead got Maybe [Char]


Let's just try to capitalize the first letter in a string (which is less cool, but actually realistic).

[String.toUpper ( List.head  x)] ++  (List.drop 1 x)

This is wrong since Char.toUpper requires String and instead List.head x is a Maybe Char .

[Char.toUpper ( List.head  x)] ++  (List.drop 1 x)

This also wrong since Char.toUpper requires Char instead of Maybe Char .

In real life a user could break a script like this by typing non-Unicode character (like an emoji). So maybe Elm's feedback is right. This should be an easy problem it takes "abcde" and turns into "AbCdE" (or possibly "aBcDe"). How to handle errors properly?

In Elm, List.head and List.tail both return they Maybe type because either function could be passed an invalid value; specifically, the empty list. Some languages, like Haskell, throw an error when passing an empty list to head or tail , but Elm tries to eliminate as many runtime errors as possible.

Because of this, you must explicitly handle the exceptional case of the empty list if you choose to use head or tail .

Note: There are probably better ways to achieve your end goal of string mixed capitalization, but I'll focus on the head and tail issue because it's a good learning tool.

Since you're using the concatenation operator, ++ , you'll need a List for both arguments, so it's safe to say you could create a couple functions that handle the Maybe return values and translate them to an empty list, which would allow you to use your concatenation operator.

myHead list =
  case List.head list of
    Just h -> [h]
    Nothing -> []

myTail list =
  case List.tail list of
    Just t -> t
    Nothing -> []

Using the case statements above, you can handle all possible outcomes and map them to something usable for your circumstances. Now you can swap myHead and myTail into your code and you should be all set.

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