Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6601375
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T18:44:40+00:00 2026-05-25T18:44:40+00:00

One day on #haskell, someone mentioned the concept of how a string’s type should

  • 0

One day on #haskell, someone mentioned the concept of how a string’s type should change when the string changes. This reminded me of some code I have in my project. It keeps bugging me, and I couldn’t articulate why. The reason, I now surmise, is because I am not implementing this concept. Here’s the code below, followed by some ideas of how I can begin to change it for the better. What I would like is some input to the effect of , “You’re on the right track.” or , “No, way off.”, or “Here’s this other thing you should be mindful of.”.

> processHTML :: String -> [[String]]
> processHTML htmlFILE =
>            let parsedHTML        = parseTags htmlFILE
>                allTagOpens       = sections (~== TagOpen "a" [("href","")]) parsedHTML
>                taggedTEXT        = head $ map (filter isTagOpen) allTagOpens
>                allHREFS          = map (fromAttrib "href") taggedTEXT
>                allPotentials     = map (dropWhile (/= '?')) allHREFS
>                removedNulls      = filter (not . null) allPotentials
>                removedQs         = map (drop 1) removedNulls
>            in map (splitOn "&") removedQs

The idea here is I’m taking raw HTML and filtering out everything I don’t want until I get what I do want. Each let binding represents a stage in filtering. This could be the foundation of a data structure, like so:

> data Stage = Stage1 Foo
>            | Stage2 Bar
>            | Stage3 Baz

Where Foo Bar and Baz are the appropriate datatype; a String, or TagOpen for example, depending on what stage I am at in the filtering process. I could use this data type to get precise information when I add in the error handling code. Plus, it could help me keep track of what is happening when.

Feedback appreciated.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T18:44:41+00:00Added an answer on May 25, 2026 at 6:44 pm

    You’re on the right track.

    First of all, when you’re building a long pipeline like this, you may prefer to compose functions directly:

    > processHTML :: String -> [[String]]
    > processHTML =
    >            parseTags
    >            >>> sections (~== TagOpen "a" [("href","")])
    >            >>> head $ map (filter isTagOpen)
    >            >>> map (fromAttrib "href")
    >            >>> map (dropWhile (/= '?'))
    >            >>> filter (not . null)
    >            >>> map (drop 1)
    >            >>> map (splitOn "&")
    

    This uses Control.Category.(>>>), which is just (at least in this case) flipped function composition.

    Now for your actual question, it looks like you’re using the tagsoup package for parsing tags. This already does some type changing throughout the pipeline: parseTags generates a Tag, some functions operate on it, and then fromAttrib goes back to a String.

    Depending on how much work you’ll be doing, I might create a newtype:

    newtype QueryElement = QE { unQE :: String } deriving (Eq, Show)
    
    > processHTML :: String -> [[QueryElement]]
    > processHTML =
    >            parseTags
    >            >>> sections (~== TagOpen "a" [("href","")])
    >            >>> head $ map (filter isTagOpen)
    >            >>> map (fromAttrib "href")
    >            >>> map (dropWhile (/= '?'))
    >            >>> filter (not . null)
    >            >>> map (drop 1)
    >            >>> map (splitOn "&" >>> map QE)
    

    Only the last line has changed here, to add the QE newtype tags to each element.

    Depending on your use case, you could take a difference approach. For example, you may want to add more information to the URI instead of just collecting the query variables. Or you might want to fold over the query items and produce a Map String String directly.

    Finally, if you’re trying to gain type safety, you usually wouldn’t make a sum type such as your Stage. This is because each constructor creates a value of the same type, so the compiler can’t do any extra checking. Instead you’d create a separate type for each stage:

    data Stage1 = Stage1 Foo
    data Stage2 = Stage2 Bar
    data Stage3 = Stage3 Baz
    
    doStage1 :: Stage1 -> Stage2
    
    doStage2 :: Stage2 -> Stage3
    

    It’s easy to create very fine-grained classes and data structures, but at some point they get out of hand. For example, in your functions allPotentials, removedNulls, and removedQs, you may want to just work on Strings. There isn’t a lot of semantic meaning that can be attached to the output of those stages, especially as they’re partial steps within a slightly larger process.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

One day I suspect I'll have to learn hadoop and transfer all this data
A sysadmin teacher told me one day that I should learn to use make
I was looking through someone's code one day and I was annoyed how they
hi I have a datepickerdialog but i´d like to change always one day before
This is a really strange issue. One day my project started to do a
Possible Duplicate: Why is String.Concat not optimized to StringBuilder.Append? One day I was ranting
I want to make the date to change one day every n seconds, like
I noticed this accidentally one day, and now decided to test it extensively. So,
One day I'll understand routing but this is what I have: public static void
string = 'one a day' how do I remove words from the string that

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.