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

  • Home
  • SEARCH
  • 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 6149553
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T19:28:14+00:00 2026-05-23T19:28:14+00:00

I’m currently reading through the paper Programming with Arrows by John Hughes and I’m

  • 0

I’m currently reading through the paper Programming with Arrows by John Hughes
and I’m already stumped on the first exercise, in section 2.5, on pg 20.

We have the Arrow and ArrowChoice typeclasses at our disposal, as well as instances for functions, stream functions [a] -> [b], and monadic functions a -> m b via the Kleisli type.

A mapA example was given:

mapA f = arr listcase >>>
         arr (const []) ||| (f *** mapA >>> arr (uncurry (:)))

Here’s an attempt:

listcase :: [a] -> (Either () (a,[a]))
listcase [] = Left ()
listcase (x:xs) = Right (x,xs)

helper :: (Bool,a) -> [a] -> Either (a,[a]) [a]
helper (True,x)  y = Left (x,y)
helper (False,x) y = Right y

test :: Arrow a => (b -> Bool) -> a (b,c) ((Bool,b), c)
test p = first (arr p &&& arr id)

filterA :: Arrow a => (b -> Bool) -> a [b] [c]
filterA p = f >>> (g ||| (h >>> (j ||| (filterA p))))
   where f = arr listcase
         g = arr (const [])
         h = test p >>> (uncurry helper)
         j = (arr id *** (filterA p)) >>> (arr (uncurry (:)))

The (bruteforce) rationale behind this futile attempt is as follows:
There are two choices to be made with filterA: the listcase like map, and the result of applying the predicate p. It starts off like map, checking the list and returning an Either value using listcase. In the case of an empty list g is applied, otherwise everything to the right of ||| is applied to a value of type (a,[a]), containing the head and tail respectively. The h function is applied first, which applies the predicate while keeping the head, returning a value of type ((Bool, head),tail). This is passed to (uncurry helper), which decides whether to keep the head or not depending on the Bool value. It returns the result as an Either value so that we may apply the choice method (|||) to it. This value is passed to the next choice: (j ||| (filterA p)) such that if the predicate held True then j is applied to a pair containing the head and tail. The head is filtered through using id while the filter p is applied to the tail. Both results are returned as a pair. This pair is then reconciled using arr (uncurry (:)) like map. Otherwise the tail is passed to filterA p alone.

I doubt it’s as difficult as I’m making it out to be, I assume I’m missing something quite obvious.

  • 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-23T19:28:16+00:00Added an answer on May 23, 2026 at 7:28 pm

    Sorry I’m not quite following your logic, but let’s see what the non-arrow code does. It

    • Checks to see if the list is empty, if so returns that
    • Otherwise, pulls the head of the list off, call the element x
    • Recurses on the rest of the list, call the result ys
    • If the predicate p is true on the head, then we append x to ys.
    • Otherwise, we return ys

    The listcase function [to implement the first 2 tasks] looks good, though remember you’re returning a list, so might as well return that instead of unit and remapping through const [].

    You have the recursion code for the third bullet buried in the two last cases, whereas I expose it directly, but that’s okay.

    For the last merging, you write it with a |||, but since you don’t need to compose any other arrows in your target category, you might as well just lift a function to do all of the work. In my code below, that’s rejoin.

    filterA :: forall arr a. ArrowChoice arr => arr a Bool -> arr [a] [a]
    filterA p = arr lstcase >>> (filterRest ||| id) where
        -- left if has a head, right otherwise
        lstcase :: [a] -> (Either (a, [a]) [a])
        lstcase (x:xs) = Left (x, xs)
        lstcase [] = Right []
    
        -- if we got a head, then
        --     for the head ("first" in code), map this to itself and p's result on it
        --     recurse on the rest of the list ("second" part)
        --     append the element to the recursion result if p's result is true
        filterRest :: arr (a, [a]) [a]
        filterRest = (first (id &&& p) >>> second (filterA p) >>> arr rejoin)
    
        rejoin :: ((a, Bool), [a]) -> [a]
        rejoin ((x, True), rest) = x:rest
        rejoin ((x, False), rest) = rest
    

    Certainly it takes time to express your ideas clearly with the likes of ***, &&&, |||, first, etc.

    A little critique.

    • Make sure you’re implementing the function they’re asking for!! If you just take a raw function p, then you might as well declare filterA = arr filter. You really want to take a lifted arrow p. That said, the change would be to simply type p instead of arr p, so your code has the right idea.
    • (uncurry helper) is not something in the arrow space, it’s just a raw function.

    When developing this stuff, I usually write a skeleton, and declare the types. That helps me figure out what’s going on. For example, I started with

    filterA :: ArrowChoice arr => arr a Bool -> arr [a] [a]
    filterA p = arr lstcase >>> (filterRest ||| id) where
        -- left if has a head, right otherwise
        lstcase :: [a] -> (Either (a, [a]) [a])
        lstcase = undefined
    
        filterRest :: arr (a, [a]) [a]
        filterRest = undefined
    

    When you add fa into the filterRest declaration however, you need to tell it that arr for filterRest is the same as the one for filterA (type variable scoping), so use the forall arr a. as above.

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

Sidebar

Related Questions

I am trying to loop through a bunch of documents I have to put
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have just tried to save a simple *.rtf file with some websites and
I have a jquery bug and I've been looking for hours now, I can't
this is what i have right now Drawing an RSS feed into the php,
I am currently running into a problem where an element is coming back from
I want use html5's new tag to play a wav file (currently only supported
I have a French site that I want to parse, but am running into
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
I have a bunch of posts stored in text files formatted in yaml/textile (from

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.