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.
Related
At the moment I'm generating strings like this:
arbStr :: Gen String
arbStr = listOf $ elements (alpha ++ digits)
where alpha = ['a'..'z']
digits = ['0'..'9']
But obviously this only generates strings from alpha num chars. How can I do it to generate from all possible chars?
Char is a instance of both the Enum and Bounded typeclass, you can make use of the arbitraryBoundedEnum :: (Bounded a, Enum a) => Gen a function:
import Test.QuickCheck(Gen, arbitraryBoundedEnum, listOf)
arbStr :: Gen String
arbStr = listOf arbitraryBoundedEnum
For example:
Prelude Test.QuickCheck> sample arbStr
""
""
"\821749"
"\433465\930384\375110\256215\894544"
"\431263\866378\313505\1069229\238290\882442"
""
"\126116\518750\861881\340014\42369\89768\1017349\590547\331782\974313\582098"
"\426281"
"\799929\592960\724287\1032975\364929\721969\560296\994687\762805\1070924\537634\492995\1079045\1079821"
"\496024\32639\969438\322614\332989\512797\447233\655608\278184\590725\102710\925060\74864\854859\312624\1087010\12444\251595"
"\682370\1089979\391815"
Or you can make use of the arbitrary in the Arbitrary Char typeclass:
import Test.QuickCheck(Gen, arbitrary, listOf)
arbStr :: Gen String
arbStr = listOf arbitrary
Note that the arbitrary for Char is implemented such that ASCII characters are (three times) more common than non-ASCII characters, so the "distribution" is different.
Since Char is an instance of Bounded as well as Enum (confirm this by asking GHCI for :i Char), you can simply write
[minBound..maxBound] :: [Char]
to get a list of all legal characters. Obviously this will not lead to efficient random access, though! So you could instead convert the bounds to Int with Data.Char.ord :: Char -> Int, and use QuickCheck's feature to select from a range of integers, then map back to a character with Data.Chra.chr :: Int -> Char.
When we do like
λ> length ([minBound..maxBound] :: [Char])
1114112
we get the number of all characters and say Wow..! If you think the list is too big then you may always do like drop x . take y to limit the range.
Accordingly, if you need n many random characters just shuffle :: [a] -> IO [a] the list and do a take n from that shuffled list.
Edit:
Well of course... since shuffling could be expensive, it's best if we chose a clever strategy. It would be ideal to randomly limit the all characters list. So just
make a limits = liftM sort . mapM randomRIO $ replicate 2 (0,1114112) :: (Ord a, Random a, Num a) => IO [a]
limits >>= \[min,max] -> return . drop min . take max $ ([minBound..maxBound] :: [Char])
Finally just take n many like random Chars like liftM . take n from the result of Item 2.
As I was working through cis 194 (week 5) I came across a problem that introduced two new concepts to me at once, and I'm having difficulty making it, at the very least, output the correct type.
My goal is to implement var in the instance declared at the bottom, however, I have never used an instance that was a function before, and nor have I used Data.Map, so I'm not very clear on what my solution syntax should even look like.
{-# LANGUAGE FlexibleInstances #-}
import qualified Data.Map as M
class HasVars a where
var :: String -> a
-- | This instance allows variables to be interpreted as functions from a
-- mapping of variables to Integer values to (possibly) Integer values
instance HasVars (M.Map String Integer -> Maybe Integer) where
-- not sure how to implement var here
So when you have
class HasVars a where
var :: String -> a
That means that, for any instance a, you have a function var :: String -> a.
So, if Map String Integer -> Maybe Integer is an instance, then that means that you have to provide a function:
var :: String -> (Map String Integer -> Maybe Integer)
Remember that (->) associates from the right, so the parentheses here are optional --
var :: String -> Map String Integer -> Maybe Integer
So, var is a function that takes a String and a Map and returns a Maybe Integer. Let's write it!
instance HasVars (Map String Integer -> Maybe Integer) where
-- var :: String -> Map String Integer -> Maybe Integer
var str mp = M.lookup str mp
And this works!
edit: Question in answer
I see that you're wondering why
var str = M.lookup str
works. Remember that M.lookup str doesn't return a Maybe Integer. It returns a Map String Integer -> Maybe Integer. Which is exactly what a should be...exactly what you want. var str is now a function that takes a map and returns a Maybe Integer.
M.lookup str doesn't have a map, yes, so it can't return a Maybe Integer. But it's a Map String Integer -> Maybe Integer. So var "hello" is now a Map String Integer -> Maybe Integer. var "hello" gives you a function that takes a map and returns a Maybe Integer. So if you give var "hello" a map, like var "hello" mp, then you get a Maybe Integer :D
So, I've come up with something that at the very least compiles. I had unnecessarily caused myself some confusion when I was attempting to solve this by repeatedly using Maybe as a constructor, and staring blankly at the error message that it wasn't defined. Just is the constructor for Maybe, Maybe isn't a constructor; too many times...
Secondly, I completely blanked by using lookup ... instead of M.lookup ..., leading to unexpected type results.
Those stumblings aside, here's what I tried
instance HasVars (M.Map String Integer -> Maybe Integer) where
var str = M.lookup str -- can be Eta-reduced
This compiles, but what doesn't make too much sense to me is that per the instance declaration, shouldn't I be providing a key-value Map? M.lookup will give back a Maybe Integer, but it just doesn't seem like I've given it enough to do that, because it needs a key and a Map, and I don't seem to have a Map. Perhaps my understanding of how class instances work is off.
I have a list of strings:
[" ix = index"," ctr = counter"," tbl = table"]
and I want to create a tuple from it like:
[("ix","index"),("ctr","counter"),("tbl","table")]
I even tried:
genTuple [] = []
genTuples (a:as)= do
i<-splitOn '=' a
genTuples as
return i
Any help would be appriciated
Thank you.
Haskell's type system is really expressive, so I suggest to think about the problem in terms of types. The advantage of this is that you can solve the problem 'top-down' and the whole program can be typechecked as you go, so you can catch all kinds of errors early on. The general approach is to incrementally divide the problem into smaller functions, each of which remaining undefined initially but with some plausible type.
What you want is a function (let's call it convert) which take a list of strings and generates a list of tuples, i.e.
convert :: [String] -> [(String, String)]
convert = undefined
It's clear that each string in the input list will need to be parsed into a 2-tuple of strings. However, it's possible that the parsing can fail - the sheer type String makes no guarantees that your input string is well formed. So your parse function maybe returns a tuple. We get:
parse :: String -> Maybe (String, String)
parse = undefined
We can immediately plug this into our convert function using mapMaybe:
convert :: [String] -> [(String, String)]
convert list = mapMaybe parse list
So far, so good - but parse is literally still undefined. Let's say that it should first verify that the input string is 'valid', and if it is - it splits it. So we'll need
valid :: String -> Bool
valid = undefined
split :: String -> (String, String)
split = undefined
Now we can define parse:
parse :: String -> Maybe (String, String)
parse s | valid s = Just (split s)
| otherwise = Nothing
What makes a string valid? Let's say it has to contain a = sign:
valid :: String -> Bool
valid s = '=' `elem` s
For splitting, we'll take all the characters up to the first = for the first tuple element, and the rest for the second. However, you probably want to trim leading/trailing whitespace as well, so we'll need another function. For now, let's make it a no-op
trim :: String -> String
trim = id
Using this, we can finally define
split :: String -> (String, String)
split s = (trim a, trim (tail b))
where
(a, b) = span (/= '=') s
Note that we can safely call tail here because we know that b is never empty because there's always a separator (that's what valid verified). Type-wise, it would've been nice to express this guarantee using a "non-empty string" but that may be a bit overengineered. :-)
Now, there are a lot of solutions to the problem, this is just one example (and there are ways to shorten the code using eta reduction or existing libraries). The main point I'm trying to get across is that Haskell's type system allows you to approach the problem in a way which is directed by types, which means the compiler helps you fleshing out a solution from the very beginning.
You can do it like this:
import Control.Monda
import Data.List
import Data.List.Split
map ((\[a,b] -> (a,b)) . splitOn "=" . filter (/=' ')) [" ix = index"," ctr = counter"," tbl = table"]
For a test app, I'm trying to convert a special type of string to a tuple. The string is always in the following format, with an int (n>=1) followed by a character.
Examples of Input String:
"2s"
"13f"
"1b"
Examples of Desired Output Tuples (Int, Char):
(2, 's')
(13, 'f')
(1, 'b')
Any pointers would be extremely appreciated. Thanks.
You can use readS to parse the int and get the rest of the string:
readTup :: String -> (Int, Char)
readTup s = (n, head rest)
where [(n, rest)] = reads s
a safer version would be:
maybeReadTup :: String -> Maybe (Int, Char)
maybeReadTup s = do
[(n, [c])] <- return $ reads s
return (n, c)
Here's one way to do it:
import Data.Maybe (listToMaybe)
parseTuple :: String -> Maybe (Int, Char)
parseTuple s = do
(int, (char:_)) <- listToMaybe $ reads s
return (int, char)
This uses the Maybe Monad to express the possible parse failure. Note that if the (char:_) pattern fails to match (i.e., if there is only a number with no character after it), this gets translated into a Nothing result (this is due to how do notation works in Haskell. It calls the fail function of the Monad if pattern matches fail. In the case of Maybe a, we have fail _ = Nothing). The function also evaluates to Nothing if reads can't read an Int at the beginning of the input. If this happens, reads gives [] which is then turned into Nothing by listToMaybe.
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!