How to determine the function of multiple composition?

Is there a way to define a Haskell function that takes (some kind of collection) of functions and creates one function: their composition from right to left?

I tried:

foldr ($)

but this only accepts a list of functions whose result is of the same type as their argument:

foldr ($) :: a -> [a -> a] -> a

So, I can do:

foldr ($) 5 [(+) 1, (*) 2] and this gives the correct result 11

However, trying to appreciate this:

foldr ($) "hello" [(+) 1, length]

produces an error below:

ERROR - type error in the list

*** Expression : [(1 +),length] *** Term : length *** Type : [a] -> Int *** Does not match : Int -> Int

+5
source share
2 answers

As always, let's put type annotations everywhere.

 -- foldr ($) "hello" [(+) 1, length] ($) :: (a -> b) -> a -> b "hello" :: [Char] (+) 1 :: Num a => a -> a length :: [a] -> Int [(+) 1, length] :: ?! 

Native Haskell folders cannot contain items of different types.

So take a step back. I will use < and > to mean "the list we want." We do not need a collection of randomly typed things. < (+) 1, length > is fine, but < length, (+) 1 > not, or rather, we need an instance of Num [a] . Similarly, if we have more than two elements: each type of element is necessarily associated with its neighbors. In addition, the general list type applies only to the types of the first and last members: what are the starting and ending types?

We can do this with GADT:

 {-# LANGUAGE GADTs #-} module SO26565306 where data F ab where FNil :: F aa (:&) :: (b -> c) -> F ab -> F ac infixr 5 :& runF :: F ab -> a -> b runF FNil = id runF (f :& fs) = f . runF fs f :: F [a] Int f = (+) 1 :& length :& FNil ghci> runF f "hello" 6 

The value f is the implementation of your desired list < (+) 1, length > .

There, for example, there is some further development of f possible - Functor and Category instances, but I do not see much sense in this. All that we have done artificially imposes a data structure on the usual functional composition. We cannot even use the GHC overloaded list of notes , which is not yet flexible enough. In addition, combining all the GADT constructors will block the optimization, almost certainly involving list switching. (I did not experiment and did not think about it carefully.)

The answer to your question

Yes, you can define a Haskell function that takes a set of functions of various but composite types and creates their composition. The type of collection I demonstrated needs the GADTs extension, which is not available in Hugs , the compiler that you seem to be using. In addition, you cannot do much with the collection. I have not proved this, but I will argue that you cannot do anything with a value of type F ab , which you cannot do with a value of type a -> b , except that it decomposes it into its components of matching with the pattern.

In other words, what you are asking is really expressed in Haskell, it is simply not clear that there is any advantage to this.

Other questions

As we said in the comments, it seems that you are looking for an analogy with Haskell for Clojure converters. Do you want to open a new question on this topic? It is a little more accurate and focused differently than this.

Bottom line

Why not just use ((+) 1) . length ((+) 1) . length ?

+5
source

The Haskell list only allows items of the same type. Just like you can’t

 ["one", 2] 

because "one" is String , and 2 is Int . You also cannot have

 [(+) 1, length] 

Since (+) 1 is Int -> Int , and length is [a] -> Int

+2
source

Source: https://habr.com/ru/post/1205510/


All Articles