Home > Enterprise >  Haskell - Apply list of functions to a variable
Haskell - Apply list of functions to a variable

Time:06-15

I have been trying to implement a function that applies a list of functions given as a parameter to a given variable. I have been running into various type errors with infinite types and type mismatches. Below is draft using recursion I believe is close to working, but keep running in to type mismatches. I am hard stuck in this swamp of issues and have no clue how to progress.

applyList :: [a -> b] -> a -> [b]
applyList [] variable = variable
applyList (f:fs) variable = applyList fs $(\f variable -> f variable)

Here is my another draft solution using foldl, no success there either.

applyList :: [a -> a] -> a -> a
applyList fs variable = foldl (\variable f -> f variable) variable fs

Example usage:

   applyList [] "foo" ==> "foo"
   applyList [] 1     ==> 1
   applyList [(  "bar")] "foo" ==> "foobar"
   applyList [reverse, tail, (  "bar")] "foo" ==> "raboo"
   applyList [(3*), (2^), ( 1)] 0 ==> 6
   applyList [( 1), (2^), (3*)] 0 ==> 2

CodePudding user response:

It looks like you're trying to write two different functions. Let's take a look at them separately. If you want this signature,

applyList :: [a -> b] -> a -> [b]

then you want to apply each function to the input and get a list of resutls. You don't need a lambda. You can simply apply f to the variable at each step of the recursion.

applyList :: [a -> b] -> a -> [b]
applyList [] _ = []
applyList (f:fs) variable = f variable : applyList fs variable

Now, Haskell provides a lot of higher-level operators for working with lists and data structures, so this sort of explicit recursion is not necessary as often as you might think. In particular, your applyList is really just the map function.

applyList :: [a -> b] -> a -> [b]
applyList fs a = map (\f -> f a) fs

And \f -> f a can be shorted to an operator section

applyList :: [a -> b] -> a -> [b]
applyList fs a = map ($ a) fs

Now the second one. If this is your goal

applyList :: [a -> a] -> a -> a

then you're right to want a fold. Based on your sample inputs and outputs, it looks like you want the rightmost function to apply first, so we can implement it with foldr

applyList :: [a -> a] -> a -> a
applyList fs a = foldr (\f a -> f a) a fs

Again, \f a -> f a is just a cute way of writing ($)

applyList :: [a -> a] -> a -> a
applyList fs a = foldr ($) a fs

If that doesn't look clear to you right now, don't fret. Stick with your recursive definition if you're more comfortable with that. This sort of higher-level thinking comes with time and experience in Haskell, and if you keep doing what you're doing, I promise you'll get there.

CodePudding user response:

Remember that the first element of the list should be the outermost function, which means you don't need to do anything backwards or use foldl. Written explicitly, it'd be like this:

applyList [] variable = variable
applyList (f:fs) variable = f (applyList fs variable)

And with foldr:

applyList = foldr (.) id
  • Related