How would I split a string after the spaces in haskell?
I know Haskell doesn't have loops, so I can't do that. I also know that recursion is "helpful" here, but that's about all I'm aware of.
So far, I've gotten a basic type signature, which is
toSplit :: String -> [String]
Basically, it changes from a string into a list of words...
Thanks!
P.S. I want to use the takeWhile
and dropWhile
functions... not a library...
string haskell recursion
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know that recursion is "helpful" here, but that's about all I'm aware of.
So far, I've gotten a basic type signature, which is
toSplit :: String -> [String]
Basically, it changes from a string into a list of words...
Thanks!
P.S. I want to use the takeWhile
and dropWhile
functions... not a library...
string haskell recursion
4
Usewords
.
– Willem Van Onsem
Nov 24 '18 at 18:36
4
Entering that type signature into hoogle gives you two options:lines
orwords
.
– hnefatl
Nov 24 '18 at 18:37
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know that recursion is "helpful" here, but that's about all I'm aware of.
So far, I've gotten a basic type signature, which is
toSplit :: String -> [String]
Basically, it changes from a string into a list of words...
Thanks!
P.S. I want to use the takeWhile
and dropWhile
functions... not a library...
string haskell recursion
I know Haskell doesn't have loops, so I can't do that. I also know that recursion is "helpful" here, but that's about all I'm aware of.
So far, I've gotten a basic type signature, which is
toSplit :: String -> [String]
Basically, it changes from a string into a list of words...
Thanks!
P.S. I want to use the takeWhile
and dropWhile
functions... not a library...
string haskell recursion
string haskell recursion
edited Nov 24 '18 at 18:44
ClaireBookworm
asked Nov 24 '18 at 18:35
ClaireBookwormClaireBookworm
14
14
4
Usewords
.
– Willem Van Onsem
Nov 24 '18 at 18:36
4
Entering that type signature into hoogle gives you two options:lines
orwords
.
– hnefatl
Nov 24 '18 at 18:37
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24
add a comment |
4
Usewords
.
– Willem Van Onsem
Nov 24 '18 at 18:36
4
Entering that type signature into hoogle gives you two options:lines
orwords
.
– hnefatl
Nov 24 '18 at 18:37
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24
4
4
Use
words
.– Willem Van Onsem
Nov 24 '18 at 18:36
Use
words
.– Willem Van Onsem
Nov 24 '18 at 18:36
4
4
Entering that type signature into hoogle gives you two options:
lines
or words
.– hnefatl
Nov 24 '18 at 18:37
Entering that type signature into hoogle gives you two options:
lines
or words
.– hnefatl
Nov 24 '18 at 18:37
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24
add a comment |
2 Answers
2
active
oldest
votes
If you want to implement that yourself, first thing you need to do is find the first word.
You can do that with:
takeWhile (/=' ') s
If the string starts with delimiter characters you need to trim those first. We can do that with dropWhile
.
takeWhile (/=' ') $ dropWhile (==' ') s
Now we have the first word, but we also need the rest of the string starting after the first word, on which we will recurse. We can use splitAt
:
(_, rest) = splitAt (length word) s
And then we recurse with the rest
of the string and cons the first word onto the result of that recursion giving us a list of all words.
And we need to define the base case, the result for the empty string which will terminate the recursion once there are no more characters.
toSplit :: String -> [String]
toSplit "" =
toSplit s =
let word = takeWhile (/=' ') $ dropWhile (==' ') s
(_, rest) = splitAt (length word) s
in word : toSplit (dropWhile (==' ') rest)
Edit: There is a bug in the code above and it's not handling an edge case properly.
The bug is that it's calling splitAt on the original s
but this gives a wrong result if s
has leading spaces:
*Main> toSplit " foo"
["foo","o"]
This should fix the bug:
let trimmed = dropWhile (==' ') s
word = takeWhile (/=' ') trimmed
(_, rest) = splitAt (length word) trimmed
That leaves one edge case:
*Main> toSplit " "
[""]
One possible solution is to use a helper function:
toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ')
where
splitWords "" =
splitWords s =
let word = takeWhile (/=' ') s
(_, rest) = splitAt (length word) s
in word : splitWords (dropWhile (==' ') rest)
2
You can usespan
instead oftakeWhile
andsplitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about usingtakeWhile
, but I definitely think thatspan
would be good too.
– ClaireBookworm
Nov 24 '18 at 19:42
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know
that recursion is "helpful" here...
Yes, Haskell use recursion rather then for
, while
loop structure that in imperative language.
In stead of write recursive function by myself, it is more common use map
, foldr (foldl)
, unfoldr
or etc recursively traverse the list. The advantage of these functions is that you can concentrate what want to do in step
function. Like your question, is suitable use unfoldr
to accomplish it.
Here is an example with takeWhile
and dropWhile
:
import Data.Char (isSpace)
import Data.List (unfoldr)
toSplit::String->[String]
toSplit = unfoldr step
where step = Nothing
step xs = Just (takeWhile (not . isSpace) xs,
(dropWhile isSpace . dropWhile (not . isSpace)) xs)
But a little bit verbose, use break
function may be more readable like:
toSplit' = unfoldr step
where step = Nothing
step xs = let (word, rest) = break isSpace xs
in Just (word, dropWhile isSpace rest)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461230%2fhow-would-i-split-a-string-after-the-spaces-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you want to implement that yourself, first thing you need to do is find the first word.
You can do that with:
takeWhile (/=' ') s
If the string starts with delimiter characters you need to trim those first. We can do that with dropWhile
.
takeWhile (/=' ') $ dropWhile (==' ') s
Now we have the first word, but we also need the rest of the string starting after the first word, on which we will recurse. We can use splitAt
:
(_, rest) = splitAt (length word) s
And then we recurse with the rest
of the string and cons the first word onto the result of that recursion giving us a list of all words.
And we need to define the base case, the result for the empty string which will terminate the recursion once there are no more characters.
toSplit :: String -> [String]
toSplit "" =
toSplit s =
let word = takeWhile (/=' ') $ dropWhile (==' ') s
(_, rest) = splitAt (length word) s
in word : toSplit (dropWhile (==' ') rest)
Edit: There is a bug in the code above and it's not handling an edge case properly.
The bug is that it's calling splitAt on the original s
but this gives a wrong result if s
has leading spaces:
*Main> toSplit " foo"
["foo","o"]
This should fix the bug:
let trimmed = dropWhile (==' ') s
word = takeWhile (/=' ') trimmed
(_, rest) = splitAt (length word) trimmed
That leaves one edge case:
*Main> toSplit " "
[""]
One possible solution is to use a helper function:
toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ')
where
splitWords "" =
splitWords s =
let word = takeWhile (/=' ') s
(_, rest) = splitAt (length word) s
in word : splitWords (dropWhile (==' ') rest)
2
You can usespan
instead oftakeWhile
andsplitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about usingtakeWhile
, but I definitely think thatspan
would be good too.
– ClaireBookworm
Nov 24 '18 at 19:42
add a comment |
If you want to implement that yourself, first thing you need to do is find the first word.
You can do that with:
takeWhile (/=' ') s
If the string starts with delimiter characters you need to trim those first. We can do that with dropWhile
.
takeWhile (/=' ') $ dropWhile (==' ') s
Now we have the first word, but we also need the rest of the string starting after the first word, on which we will recurse. We can use splitAt
:
(_, rest) = splitAt (length word) s
And then we recurse with the rest
of the string and cons the first word onto the result of that recursion giving us a list of all words.
And we need to define the base case, the result for the empty string which will terminate the recursion once there are no more characters.
toSplit :: String -> [String]
toSplit "" =
toSplit s =
let word = takeWhile (/=' ') $ dropWhile (==' ') s
(_, rest) = splitAt (length word) s
in word : toSplit (dropWhile (==' ') rest)
Edit: There is a bug in the code above and it's not handling an edge case properly.
The bug is that it's calling splitAt on the original s
but this gives a wrong result if s
has leading spaces:
*Main> toSplit " foo"
["foo","o"]
This should fix the bug:
let trimmed = dropWhile (==' ') s
word = takeWhile (/=' ') trimmed
(_, rest) = splitAt (length word) trimmed
That leaves one edge case:
*Main> toSplit " "
[""]
One possible solution is to use a helper function:
toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ')
where
splitWords "" =
splitWords s =
let word = takeWhile (/=' ') s
(_, rest) = splitAt (length word) s
in word : splitWords (dropWhile (==' ') rest)
2
You can usespan
instead oftakeWhile
andsplitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about usingtakeWhile
, but I definitely think thatspan
would be good too.
– ClaireBookworm
Nov 24 '18 at 19:42
add a comment |
If you want to implement that yourself, first thing you need to do is find the first word.
You can do that with:
takeWhile (/=' ') s
If the string starts with delimiter characters you need to trim those first. We can do that with dropWhile
.
takeWhile (/=' ') $ dropWhile (==' ') s
Now we have the first word, but we also need the rest of the string starting after the first word, on which we will recurse. We can use splitAt
:
(_, rest) = splitAt (length word) s
And then we recurse with the rest
of the string and cons the first word onto the result of that recursion giving us a list of all words.
And we need to define the base case, the result for the empty string which will terminate the recursion once there are no more characters.
toSplit :: String -> [String]
toSplit "" =
toSplit s =
let word = takeWhile (/=' ') $ dropWhile (==' ') s
(_, rest) = splitAt (length word) s
in word : toSplit (dropWhile (==' ') rest)
Edit: There is a bug in the code above and it's not handling an edge case properly.
The bug is that it's calling splitAt on the original s
but this gives a wrong result if s
has leading spaces:
*Main> toSplit " foo"
["foo","o"]
This should fix the bug:
let trimmed = dropWhile (==' ') s
word = takeWhile (/=' ') trimmed
(_, rest) = splitAt (length word) trimmed
That leaves one edge case:
*Main> toSplit " "
[""]
One possible solution is to use a helper function:
toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ')
where
splitWords "" =
splitWords s =
let word = takeWhile (/=' ') s
(_, rest) = splitAt (length word) s
in word : splitWords (dropWhile (==' ') rest)
If you want to implement that yourself, first thing you need to do is find the first word.
You can do that with:
takeWhile (/=' ') s
If the string starts with delimiter characters you need to trim those first. We can do that with dropWhile
.
takeWhile (/=' ') $ dropWhile (==' ') s
Now we have the first word, but we also need the rest of the string starting after the first word, on which we will recurse. We can use splitAt
:
(_, rest) = splitAt (length word) s
And then we recurse with the rest
of the string and cons the first word onto the result of that recursion giving us a list of all words.
And we need to define the base case, the result for the empty string which will terminate the recursion once there are no more characters.
toSplit :: String -> [String]
toSplit "" =
toSplit s =
let word = takeWhile (/=' ') $ dropWhile (==' ') s
(_, rest) = splitAt (length word) s
in word : toSplit (dropWhile (==' ') rest)
Edit: There is a bug in the code above and it's not handling an edge case properly.
The bug is that it's calling splitAt on the original s
but this gives a wrong result if s
has leading spaces:
*Main> toSplit " foo"
["foo","o"]
This should fix the bug:
let trimmed = dropWhile (==' ') s
word = takeWhile (/=' ') trimmed
(_, rest) = splitAt (length word) trimmed
That leaves one edge case:
*Main> toSplit " "
[""]
One possible solution is to use a helper function:
toSplit :: String -> [String]
toSplit = splitWords . dropWhile (==' ')
where
splitWords "" =
splitWords s =
let word = takeWhile (/=' ') s
(_, rest) = splitAt (length word) s
in word : splitWords (dropWhile (==' ') rest)
edited Nov 25 '18 at 19:36
answered Nov 24 '18 at 19:05
StefanStefan
60028
60028
2
You can usespan
instead oftakeWhile
andsplitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about usingtakeWhile
, but I definitely think thatspan
would be good too.
– ClaireBookworm
Nov 24 '18 at 19:42
add a comment |
2
You can usespan
instead oftakeWhile
andsplitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about usingtakeWhile
, but I definitely think thatspan
would be good too.
– ClaireBookworm
Nov 24 '18 at 19:42
2
2
You can use
span
instead of takeWhile
and splitAt
– 4castle
Nov 24 '18 at 19:41
You can use
span
instead of takeWhile
and splitAt
– 4castle
Nov 24 '18 at 19:41
Wow! Thanks!. @4castle In the question, I was asking about using
takeWhile
, but I definitely think that span
would be good too.– ClaireBookworm
Nov 24 '18 at 19:42
Wow! Thanks!. @4castle In the question, I was asking about using
takeWhile
, but I definitely think that span
would be good too.– ClaireBookworm
Nov 24 '18 at 19:42
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know
that recursion is "helpful" here...
Yes, Haskell use recursion rather then for
, while
loop structure that in imperative language.
In stead of write recursive function by myself, it is more common use map
, foldr (foldl)
, unfoldr
or etc recursively traverse the list. The advantage of these functions is that you can concentrate what want to do in step
function. Like your question, is suitable use unfoldr
to accomplish it.
Here is an example with takeWhile
and dropWhile
:
import Data.Char (isSpace)
import Data.List (unfoldr)
toSplit::String->[String]
toSplit = unfoldr step
where step = Nothing
step xs = Just (takeWhile (not . isSpace) xs,
(dropWhile isSpace . dropWhile (not . isSpace)) xs)
But a little bit verbose, use break
function may be more readable like:
toSplit' = unfoldr step
where step = Nothing
step xs = let (word, rest) = break isSpace xs
in Just (word, dropWhile isSpace rest)
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know
that recursion is "helpful" here...
Yes, Haskell use recursion rather then for
, while
loop structure that in imperative language.
In stead of write recursive function by myself, it is more common use map
, foldr (foldl)
, unfoldr
or etc recursively traverse the list. The advantage of these functions is that you can concentrate what want to do in step
function. Like your question, is suitable use unfoldr
to accomplish it.
Here is an example with takeWhile
and dropWhile
:
import Data.Char (isSpace)
import Data.List (unfoldr)
toSplit::String->[String]
toSplit = unfoldr step
where step = Nothing
step xs = Just (takeWhile (not . isSpace) xs,
(dropWhile isSpace . dropWhile (not . isSpace)) xs)
But a little bit verbose, use break
function may be more readable like:
toSplit' = unfoldr step
where step = Nothing
step xs = let (word, rest) = break isSpace xs
in Just (word, dropWhile isSpace rest)
add a comment |
I know Haskell doesn't have loops, so I can't do that. I also know
that recursion is "helpful" here...
Yes, Haskell use recursion rather then for
, while
loop structure that in imperative language.
In stead of write recursive function by myself, it is more common use map
, foldr (foldl)
, unfoldr
or etc recursively traverse the list. The advantage of these functions is that you can concentrate what want to do in step
function. Like your question, is suitable use unfoldr
to accomplish it.
Here is an example with takeWhile
and dropWhile
:
import Data.Char (isSpace)
import Data.List (unfoldr)
toSplit::String->[String]
toSplit = unfoldr step
where step = Nothing
step xs = Just (takeWhile (not . isSpace) xs,
(dropWhile isSpace . dropWhile (not . isSpace)) xs)
But a little bit verbose, use break
function may be more readable like:
toSplit' = unfoldr step
where step = Nothing
step xs = let (word, rest) = break isSpace xs
in Just (word, dropWhile isSpace rest)
I know Haskell doesn't have loops, so I can't do that. I also know
that recursion is "helpful" here...
Yes, Haskell use recursion rather then for
, while
loop structure that in imperative language.
In stead of write recursive function by myself, it is more common use map
, foldr (foldl)
, unfoldr
or etc recursively traverse the list. The advantage of these functions is that you can concentrate what want to do in step
function. Like your question, is suitable use unfoldr
to accomplish it.
Here is an example with takeWhile
and dropWhile
:
import Data.Char (isSpace)
import Data.List (unfoldr)
toSplit::String->[String]
toSplit = unfoldr step
where step = Nothing
step xs = Just (takeWhile (not . isSpace) xs,
(dropWhile isSpace . dropWhile (not . isSpace)) xs)
But a little bit verbose, use break
function may be more readable like:
toSplit' = unfoldr step
where step = Nothing
step xs = let (word, rest) = break isSpace xs
in Just (word, dropWhile isSpace rest)
edited Nov 25 '18 at 8:22
answered Nov 25 '18 at 7:32
assembly.jcassembly.jc
2,0891214
2,0891214
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461230%2fhow-would-i-split-a-string-after-the-spaces-in-haskell%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
Use
words
.– Willem Van Onsem
Nov 24 '18 at 18:36
4
Entering that type signature into hoogle gives you two options:
lines
orwords
.– hnefatl
Nov 24 '18 at 18:37
"...Haskell doesn't have loops..." Yes, because recursion replaces loops. This is why recursion is helpful here.
– AJFarmar
Nov 24 '18 at 19:24