Func<Func<T,T>,T>
without using constructions like default (T)
he plunged me into deep cognitive dissonance.T Fix<T>(Func<T,T> func){
return func(Fix(func));
}
I could not even think. Is it possible to do such a function? It will be called endlessly and will not work. In languages like C #, such a construction will actually cause looping, but it can work in languages like python or haskel. Now there will be some Haskell code, I hope the syntax will be more or less clear to everyone. fix f = f( fix f)
const42 x = 42
print (fix const42) -- , ?
If we expand the challenge, we will see that the following chain of calculations takes place:fix const42 -> const42 ( fix const42) -> 42
The last transition is due to the fact that we do not need a function argument to calculate its value.: Is the function of adding an item to the head of the list. For example: 1:[2,3] = [1,2,3], n:[] = [n]
fix (1:)
function. It returns a list that will obviously be infinite, but you can still use it.take 3 (fix (1:)) -> take 3 (1:fix (1:)) -> 1:take 2 (fix (1:)) -> 1:(1:take 1 (fix (1:)))
-> 1:(1:(1:take 0 (fix (1:)))) -> 1:(1:(1:[])) -> 1:(1:[1]) -> 1:[1,1] -> [1,1,1]
So simply we got the result from the function that uses its parameter. We even created a useful thing:repeat n = fix (n:)
- Generate an infinite list of one repeating element.factCore f = \x -> if x == 0 then 1 else x * f (x-1)
Then the fix factCore
function will be an ordinary factorial. In fact, each time instead of the function f, the factCore function will be substituted, which is why everything will become extremely similar to ordinary recursion.allDiffCore nf = \k cond -> if k == 1 then map (\x->[x]) $ filter cond [1..n] else concat $ map (\x -> map (x:) (f (k-1) (/=x)) ) ( filter cond [1..n])
sequences nk = fix (allDiffCore n) k (\x->True)
Small explanations:At each step, we take several suitable elements and set a function that determines whether the next element fits. With this pattern, you can generate many different sequences. For example, to get ever-increasing sequences, it is enough to change the part responsible for the filtering function, that is, replace (/ = x) with (> x).filter
is a function that takes two parameters: conditions and a list. Returns a list of objects that satisfy the condition./=
- ordinary "not equal". Such is the very mathematical record.concat
is a function that combines the list of lists into one list.
public static Func<T1, T2> Fix<T1, T2>(Func<Func<T1, T2>, Func<T1, T2>> f)
{
// ,
// .
return f(x => Fix(f)(x));
}
And further use:var fact = Fix< int , int >(self => x =>
{
if (x == 0)
return 1;
return x * self(x - 1);
});
var result = fact(5); // 120
Source: https://habr.com/ru/post/79713/
All Articles