views:

593

answers:

4
+1  Q: 

Casting in Haskell

a) I need to cast from String to int in haskell. I have a function that gets the third word in a sentence as a string, but my third word in all my sentences are numbers (int), how can I cast from string to int so then I can use the number afterwards to do operations like add or mult?

getThirdWord :: String -> String
getThirdWord = head . tail . tail . words

b) I'm using Visual Haskell Studio. How can I use functions like map and zip in visual haskell studio? Are there any plugins that I need to include to my vhs to make them work?

Thank you so much in advance!

+4  A: 

Regarding casting, take a look at the read function.

getThirdWord :: String -> Int
getThirdWord = read . head . tail . tail . words

Visual Haskell Studio seems to be an IDE only, in that the backend uses GHC, which fully supports the Haskell specification and includes the libraries that include map and fold.

Yacoby
I think you want `read .` instead of `read $`.
Jason Orendorff
+9  A: 

Yacoby's answer is correct of course. Let me make two remarks:

  1. read is very general. It not only converts String to Int. Its return type depends on the context. In this case getThirdWord is defined to be String -> Int, so read knows what to do. This is not always the case, so if you ever get a compile error while using read, remember this: you may need to help Haskell figure out the return type.
  2. Currently you use head . tail . tail to get the third list element. What if you wanted, say, the 23rd element? A more maintainable and readable solution is to use (!!): this way you can retrieve a list element at any index. Thus:

    thirdWordAsInt :: String -> Int 
    thirdWordAsInt = read . (!! 2) . words
    

    (Note the 2 instead of a 3, since indices are 0-indexed.)

Stephan202
+2  A: 

I second Yacoby to use read, but keep in mind that both head/tail and read are partial functions and may fail on empty list. I think it's better to avoid head if you can use pattern matching instead. For example,

get3rd :: String -> String
get3rd s =
  case (take 3 $ words s) of
    [_,_,w]   -> w
    otherwise -> ""

This function is safe for any input (it just returns an empty string if there are less than 3 words). Certainly, if you are absolutely sure the lists are always non-empty, you can use head/tail.

With read you can either catch exceptions (not very convenient), or use reads instead:

toInt :: String -> Maybe Int
toInt s =
  case reads s of
    [(i,_)]   -> Just i
    otherwise -> Nothing

-- test cases
main = do
  print . toInt . get3rd $ "1 2 3"
  print . toInt . get3rd $ "one two three"
  print . toInt . get3rd $ "short list"

This toInt returns Just a number or Nothing if it cannot parse. Alternatively you can use Safe library and its readMay function.

jetxee
You should add that it's perfectly fine to use `last` and `head` as long as you know for sure that you wont be dealing with an empty list.
Rayne
I agree Rayne and updated the answer.
jetxee
A: 

You guys are all right, but I post because I think there is a very elegant and useful function I came up with when learning to help with the reading and showing of text.

as :: (Read a, Show a) => (a -> a) -> String -> String
as f = show . f . read

Prelude> as (+1) "7"
"8"

Prelude> as (+(1/2)) "5"
"5.5"

Useful, eh? =P. Also xs !! n gets xs's n'th element. Look at others answers for easy ways to print.

codebliss
Why not `(Read a, Show b) => (a -> b) -> String -> String` as the type?
sepp2k
Touche. Yours makes sense, I guess I just did this for simplicity.
codebliss