so I have this code fragment: where exponent = read (tail (dropWhile (/= '^') (head xs))) :: Int but there is a possibility of the list inside tail being empty, so that would mean there would be an error looking for a tail inside an empty list. Is there a way to do something like: if error: exponent = 1 ?
Here is the full function if it helps in any way :)
internalRepresentation :: [String] -> [(Int,Char ,Int)]
internalRepresentation xs
|null xs = []
|all isDigit (head xs) = (read (head xs), ' ', 0) : internalRepresentation (tail xs)
|head (head xs) == '-' = (-read (takeWhile isDigit (pos_mon)) :: Int, head (dropWhile isDigit (pos_mon)), exponent) : internalRepresentation (drop 1 xs)
|otherwise = (read (takeWhile isDigit (head xs)) :: Int, head (dropWhile isDigit (head xs)), exponent) : internalRepresentation (drop 1 xs)
where pos_mon = tail (head xs)
exponent = read (tail (dropWhile (/= '^') (head xs))) :: Int
Thanks for your time!
The functions read, head, and tail are partial which means that they can fail with an error as you have experienced. That is why many people avoid those functions. Personally, I would write it like this:
import Text.Read (readMaybe)
internalRepresentation' :: String -> (Int, Char, Int)
internalRepresentation' xs =
case reads xs of
[(n, "")] -> (n, ' ', 0)
[(n, x:xs')] ->
case readMaybe (drop 1 (dropWhile (/= '^') (x:xs'))) of
Just e -> (n, x, e)
Nothing -> error "Malformed exponent"
_ -> error "Malformed internal representation"
internalRepresentation :: [String] -> [(Int, Char, Int)]
internalRepresentation xs = map internalRepresentation' xs
You can probably avoid that ugly drop 1 (dropWhile (/= '^') (x:xs')) too if you constrain your input a bit more. But I'm not completely sure what this function is actually supposed to do, so I can't help much more.
For example, if you only want to parse strings that look exactly like 123^456 (without other characters in between), then you can write it like this:
internalRepresentation' xs =
case reads xs of
[(n, "")] -> (n, ' ', 0)
[(n, '^':xs')] ->
case readMaybe xs' of
Just e -> (n, '^', e)
Nothing -> error "Malformed exponent"
_ -> error "Malformed internal representation"
Related
Im getting parse error on my if then else statement and I dont understand why. I have checked the functions, and as far as I can tell all of them are getting the arguments they need, so I dont understand why this is happening. Im very new to haskell so help in understanding this would be deeply appreciated.
replace :: [(Int,Int)] -> String -> String
replace xs ys = if translate (manipulator (fst (convert xs)) (snd (convert xs)) ys) /= ""
then take (fst (convert xs)) ys ++ (manipulator (fst (convert xs)) (snd (convert xs)) ys) ++ drop (snd (convert xs)) ys
else take (fst (convert xs)) ys ++ stjerner (snd (convert xs) - fst (convert xs)) ++ drop (snd (convert (xs)) ys
--get parse error here, see picture.
stjerner :: Int -> String
stjerner 0 = ""
stjerner int | int > 0 = "*" ++ stjerner (int -1)
manipulator:: Int -> Int -> String -> String
manipulator low high xs = take high (drop low xs)
convert :: [a] -> a
convert [a] = a
picture of parse error here
The last expression in you else clause --- drop (snd (convert (xs)) ys -- is misparenthesized. You've got 3 open parens but only 2 close parens. I think you meant drop (snd (convert xs)) ys.
I would like to incorporate Maybe [int] into this.
The code should take a string and filter out spaces turning it into a list of integers and if their are letters return Nothing.
text2digits :: String -> [Int]
text2digits s = case s of
[] -> []
x:xs
|isDigit x -> digitToInt x :text2digits (filter (/= ' ') xs)
|otherwise -> undefined
input "1233 5687" output: [1,2,3,3,5,6,8,7]
input "a89" required output : Nothing
current output: undefined
I have tried this but it shows up a list of errors
text2digits :: String -> Maybe [Int]
text2digits s = case s of
[] -> Just []
x:xs
|isDigit x -> Just digitToInt x :text2digits (filter (/= ' ') xs)
|otherwise -> Nothing
What is wrong with the code, that you've specified for text2digits :: String -> Maybe [Int]?
The problem is in this line:
digitToInt x :text2digits (filter (/= ' ') xs)
text2digits returns value of Maybe [Int] type, but (:) expects it to be [Int].
In order to fix it, you can use fmap or <$> to apply a function to a structure inside the functor Maybe:
import Data.Char
text2digits :: String -> Maybe [Int]
text2digits s = case s of
[] -> Just []
x:xs
|isDigit x -> ((digitToInt x) :) <$> text2digits (filter (/= ' ') xs)
|otherwise -> Nothing
main = print $ text2digits "1233 5687"
Or probably you can use traverse to refactor the function a bit:
import Data.Char
text2digits :: String -> Maybe [Int]
text2digits s =
traverse digitToMaybeInt $ filter (/= ' ') s
where
digitToMaybeInt x
| isDigit x = Just $ digitToInt x
| otherwise = Nothing
main = print $ text2digits "89"
Hi i am trying to do a function input is a list of strings, and the output is again a list of all words occurring in the input.
for example input ["For example,", "love,", "hate."]
output ["For","example","love","hate"]
atm i have this. Any help would be appreciated. Also how can i remove the blank space with just one function and in linear time?
And not using any existing function
split' :: String -> [String]
split' [] = []
split' (x:xs)
| isBlank x = split' xs
| otherwise = waitForBlank (x:xs) : split' (drop (length (waitForBlank (x:xs))) xs)
isBlank :: Char -> Bool
isBlank x = if x == ' ' then True else False
waitForBlank :: String -> String
waitForBlank [] = []
waitForBlank (x:xs)
| isBlank x = []
| otherwise = x : waitForBlank xs
There's a cool one-line to perform what you need
["For example,", "love,", "hate."] >>= words
>>= has type (>>=) :: Monad m => m a -> (a -> m b) -> m b, which takes a function which returns a monadic structure and joins the result into the monadic structure.
If you want to implement words by yourself:
words' xs =
let
waitForBlank (acc, buff) [] = (acc ++ [buff], buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank (acc ++ [buff], []) xs
else
waitForBlank (acc, buff ++ [x]) xs
in
fst (waitForBlank ([], []) xs)
Or with using (:) and reverse the result (for better performance):
words'' xs =
let
waitForBlank (acc, buff) [] = (reverse (buff : acc), buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank ((reverse buff) : acc, []) xs
else
waitForBlank (acc, x:buff) xs
in
fst (waitForBlank ([], []) xs)
How can I write a takeWhile that would keep the first element that doesn't match the condition?
Example (obviously my example is trickier than this) :
Instead of takeWhile (\× - > x! = 3) [1..10] to return [1,2] I need [1,2,3].
I thought of (takeWhile myFunc myList) ++ [find myFunc myList] but it means I need to go through my list 2 times...
Any idea?
You can use span or break.
λ> span (/=3) [1..10]
([1,2],[3,4,5,6,7,8,9,10])
So you can do something like this:
takeWhileInc :: (a -> Bool) -> [a] -> [a]
takeWhileInc p xs = case zs of [] -> error "not found"
(z:_) -> ys ++ [z]
where
(ys, zs) = span p xs
(Or whatever you want to happen when zs is empty because no 3
was found.)
You can roll your own.
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p = foldr (\x ys -> if p x then x:ys else [x]) []
Compare it with
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p = foldr (\x ys -> if p x then x:ys else []) []
Explicit recursion would also be fine for this.
takeWhileOneMore :: (a -> Bool) -> [a] -> [a]
takeWhileOneMore p [] = []
takeWhileOneMore p (x:xs) =
if p x
then x : takeWhileOneMore p xs
else [x]
I like to use the base function more than many people do, such as re-using takeWhile in an intelligent way to get the desired result. For example, you can create a new list of predicates with the first element being True and takeWhile this list is true:
takeWhileP1 p xs = map snd (takeWhile fst (zip (True:map p xs) xs)
This generalizes nicely as well (not necessarily efficient in this form):
takeWhilePlusN n p xs = map snd (takeWhile fst (zip (replicate n True ++ map p xs) xs))
Or perhaps easier to read:
takeWhilePlusN n p xs =
let preds = replicate n True ++ map p xs
annotated = zip preds xs
in map snd (takeWhile fst annotated)
And the result:
*Main> takeWhilePlusN 3 (<5) [1..10]
[1,2,3,4,5,6,7]
*Main> takeWhilePlusN 1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhileP1 (<5) [1..10]
[1,2,3,4,5]
*Main> takeWhile (<5) [1..10]
[1,2,3,4]
When the condition fails for a element, instead of terminating with empty list, we can return the element.
takeWhileInclusive :: (a->Bool) -> [a] -> [a]
takeWhileInclusive _ [] = []
takeWhileInclusive predicate (x:xs) = if predicate x
then do (x: takeWhileInclusive predicate xs)
else [x]
I'm playing with Difference list data type in Haskell: http://hackage.haskell.org/package/dlist-0.8.0.2/docs/Data-DList.html
And I see from package description that head function runs in O(n) time.
I wonder, why it happens? From first glance it looks like head should work O(1) time in most reasonable cases. But to argue about time-complexity we should define what this n stands for? Is it number of elements or number of lists?
Let's expand some definitions to figure out how head works.
First I have x = [1,2] and y = [3,4]. Then I convert them to DList and obtain x' = DList (x++) and y' = DList (y++). After that I append them:
z = x' <> y' = DList $ \zs -> x ++ (y ++ zs)
Now to the head function. It is defined as
-- | /O(n)/. Return the head of the dlist
head :: DList a -> a
head = list (error "Data.DList.head: empty dlist") const
Where list is:
-- | /O(n)/. List elimination for dlists
list :: b -> (a -> DList a -> b) -> DList a -> b
list nill consit dl =
case toList dl of
[] -> nill
(x : xs) -> consit x (fromList xs)
So you can say it is obvious why head runs O(n) time: is uses list function which runs O(n) time. But let's do some equational reasoning:
head z
= list (error "Data.DList.head: empty dlist") const z
= case toList z of
[] -> error "Data.DList.head: empty dlist"
(x : xs) -> const x (fromList xs)
= case (toList $ DList $ \zs -> x ++ (y ++ zs)) of
[] -> error "Data.DList.head: empty dlist"
(x : xs) -> const x (fromList xs)
= case (x ++ (y ++ [])) of
[] -> error "Data.DList.head: empty dlist"
(x : xs) -> const x (fromList xs)
= case ((1:2:[]) ++ (y ++ [])) of
[] -> error "Data.DList.head: empty dlist"
(x : xs) -> const x (fromList xs)
= case (1:((2:[]) ++ (y ++ []))) of
[] -> error "Data.DList.head: empty dlist"
(x : xs) -> const x (fromList xs)
= (1 : ((2:[]) ++ (y ++ []))) -> const 1 (fromList (2:[]) ++ (y ++ []))
= 1
So it looks like head won't evaluate whole list to take just first element and will work in O(1) unless there no empty lists. Is this really true and description of function just tells about worst possible case?