Char to string function - haskell

I have a very simple question: Given a function accepting a char and returning a string
test :: Char -> [String]
how can one convert the char into a string? I'm confused over the two types.

In Haskell String is an alias for [Char]:
type String = [Char]
If you just want a function that converts a single char to a string you could e.g. do
charToString :: Char -> String
charToString c = [c]
If you prefer pointfree style you could also write
charToString :: Char -> String
charToString = (:[])

A String is just a [Char]
But that's just a nice way of saying
'H':'E':'L':'L':'O':[]
So to make it a [String] we could do:
['H':'E':'L':'L':'O':[]]

Another way would be using
return . return
Since return for lists is defined as :[]

Note that you can convert any type implementing the Show type class to a string using show:
(Show a) => a -> String
Because Char implements this, the function is already written for you!

Related

Haskell function incompatible type and definition

I'm trying to understand this function (taken from here)
escape :: String -> String
escape =
let
escapeChar c =
case c of
'<' -> "<"
'>' -> ">"
_ -> [c]
in
concat . map escapeChar
My questions are:
According to the type, escape is a function that takes a String. But it seems that in in the fuction definition it does not receive any argument. How does this work?
What is the relationship between escapeChar and c? How is that relationship established? Does c coming right after escapeChar have a meaning?
Would it be easier if escapeChar were a top-level definition using pattern matching:
escape :: String -> String
escape = concatMap escapeChar
escapeChar :: Char -> String
escapeChar '<' = "<"
escapeChar '>' = ">"
escapeChar ch = [ch]
[ch] is a singleton list, it turns ch :: Char into a [ch] :: String.
In Haskell you can remove/add an argument from/to each side (eta conversion). escape is the eta reduced form of
escape :: String -> String
escape str = concatMap escapeChar str
Just like, if you wanted to define a synonym for (+) you have equivalent ways of writing it. I feel like the add = (+) is clearest, you are identifying the two functions. The arguments are the same on both sides so we don't specify them.
add :: Int -> Int -> Int
add = (+)
add a = (+) a
add a = (a +)
add a b = (+) a b
add a b = a + b
These are equivalent ways of writing escape:
escape = concat . map escapeChar
escape str = concat (map escapeChar str)
According to the type, escape is a function that takes a String. But it seems that in in the fuction definition it does not receive any argument. How does this work?
concat . map escape returns a function. That function will take a string and process it.
What is the relationship between escapeChar and c? How is that relationship established? Does c coming right after escapeChar have a meaning?
Yes, it is the first (and only) parameter of the function. It is a Character, and the escapeChar function maps that Char on a String. The let clause thus defines a function escapeChar :: Char -> String that will then be used in concat . map escape (or perhaps better concatMap escape). This will map each Char of the given String to a substring, and these are then concatenated together as a result.
the map function has a signature (a -> b) -> ([a] -> [b]) this means that the map function takes in a function(the escapeChar function) and returns a function that converts a list using that function(the escapeChar function). map escapeChar returns a function that converts a string using the escapeChar function on each character in the string.

Returning a function

I have been tasked with this:
Write a function enc :: Int -> String -> String that encrypts a string by adding some given integer to each character's Unicode value. Now, using enc as a locally declared function write a function encrypt :: Int -> String -> (String , String -> String) that accepts a String and an Int and returns a pair of an encrypted string and a function with which to decrypt the string.
I have written the function enc, that was fairly easy, but I cannot figure out how to return a function from encrypt.
So far I have
encrypt :: Int -> String -> (String , String -> String)
encrypt num word = (enc num word, ???)
I have no idea what to write in place of '???'. I've read a fair bit about curried functions but everything I've found defines a function that takes a function as a parameter and uses that function to recursively call itself. encrypt doesn't take a function as a parameter. How can I define an entirely new function and return it, rather than returning its value, all from within another function?
There's the explicit lambda approach that declares a function with a parameter:
-- Expression is of the type String -> String
-- Similar to python lambda mystring: enc(-num, mystring)
-- or java (mystring) => enc(-num, mystring)
\mystring -> enc (-num) mystring
However, thanks to currying, you can just take enc :: Int -> String -> String and give it an int, which will result in a String -> String:
-- Also of the type String -> String
enc (-num)
A lambda expression would be the most direct way, as others pointed out. Note that you can still simply define your own function and return it, e.g.
encrypt :: Int -> String -> (String , String -> String)
encrypt num word = (enc num word, myFunction)
where
myFunction :: String -> String
myFunction str = .... -- here you can use num, word, str to produce the result you need

Checking for all lowercase & Combining a Word with a List - Haskell

I am having some trouble writing 2 separate functions. One of which "isWord s" is to take in a word and return "true" if all characters of the word are lowercase, otherwise return "false". Below is an example:
isWord "foo" = True; isWord "fo3o" = False
It must use this definition:
isWord :: String -> Bool
isWord s =
The other function "prefixWords str strs" which takes a word and a list of words and combines the two in a list with a ":" between each word. Shown below as an example:
prefixWords "word:" ["aa", "a3", "foo"] = ["word:aa", "word:foo"]
It must use this definition:
prefixWords :: String -> [String] -> [String]
prefixWords str strs =
Any help is greatly appreciated as I am brand new to Haskell and don't have any idea of where to start. Thanks!
Since this is clearly homework, I won't give you the answers, just a large nudge.
First off, String is just a synonym for [Char].
These functions may be helpful:
(++) :: [a] -> [a] -> [a]
This will concatenate two lists or strings.
import Data.Char
isLower :: Char -> Bool
This will test if a Char is lowercase or not
all :: (a -> Bool) -> [a] -> Bool
This will test whether or not all of a lists elements satisfy a predicate.
map :: (a -> b) -> [a] -> [b]
This applies a function to all elements of a list.
For your function isWord, you need to check that all of a strings elements are/isLower.
For your function prefixWords, every element is concatenated with a given string.

Reading String in Haskell

I'm trying to write a function that reads from a String in Haskell, if the String has a number, it should return True.
This is what I currently have
hasNumber :: String -> Bool
hasNumber n = any number
I have tried lots of functions in the second line but it doesn't seem to work, can anyone help me?
Thank you!
Assuming you want to check whether your string is an natural number it boils down to
import Data.Char (isDigit)
hasNumber :: String -> Bool
hasNumber = all isDigit
If you don't want to use Data.Char (or aren't allowed if this is an assignment), you can use
isDigit = (`elem` ['0'..'9'])
If you want to check whether the number is integral, you have to check whether the string starts with a '-', and if it does, whether the rest of the string is a natural number:
isIntegral :: String -> Bool
isIntegral ('-':[]) = False -- string is "-", which isn't a number
isIntegral ('-':xs) = hasNumber xs -- string is "-....", so we check "...."
isIntegral x = hasNumber x -- string doesn't start with '-'
Should refine what you want by "number", but supposing you want to simply read one of the Haksell numeric types formatted as a string in the way Haskell prints them, then you can use the readMaybe function.
import Text.Read
hasNumber :: String -> Bool
hasNumber x = isJust ( readMaybe x :: Maybe Int )
If you want to read a different numeric type than change the type annotation to Maybe Double, Maybe Integer or whatever you want.
If you need to parse a variety of number formats that differ from the way that Haskell shows them by default, then use a parser library like Parsec.

Mapping 3 argument function to a list in Haskell

The map function works fine on really easy functions that take no arguments like *7 to every element in a list of Ints.
But say I made a custom function that takes a Char, String and Int and then returns a Char and I wanted to apply this function to a list of Chars i.e. a String to get a String back after applying the other function to each Char? When I try this all I get is error messages?
Put your Char argument to the last position:
foo :: String -> Int -> Char -> Char
foo str num c = c
bar = map (foo str num)
But we really need some more information from your side to help you better. Can you add the code you tried to write to your question?

Resources