Posts

....
Technical Blog for .NET Developers ©

Showing posts with label F#. Show all posts
Showing posts with label F#. Show all posts

Wednesday, January 12, 2022

C# & F# : Real Curry

This post is dedicated to extend a functionality coded in this previous post:

FSharp InvokeFast

Curry is a basic concept on functional programming, let's extend the defintion wth this post

Curry: Wikipedia, the free encyclopedia

In this post we code with C# Real Curry with the implementation of F#

We begin with the definition of a Curry Interface


  
    public interface ICurriedFunction<T, S, M, R>
    {
        /// <summary> Invokes the value Result
        R InvokeResult();

        /// <summary> Sets Arg1, Arg2, Arg3
        ICurriedFunction<T, S, M, R> SetArgs(Expression<Func<T>> funcArg1, Expression<Func<T, S>> funcArg2, Expression<Func<S, M>> funcArg3);

        /// <summary> Sets the Result and Curried functions
        ICurriedFunction<T, S, M, R> SetResultFunction(Converter<M, R> converter);        
    }
  
  


With this implementation



    public abstract class SpeciedFunction<R>
    {
        public abstract R InvokeResult();
    }
    
    public class CurriedFunction<T, S, M, R> : SpeciedFunction<R>, ICurriedFunction<T, S, M, R>
    {
        private FSharpFunc<T, FSharpFunc<S, FSharpFunc<M, R>>> Func { get; set; }

        private FSharpFunc<M, R> ResultFunc { get; set; }

        private FSharpFunc<S, FSharpFunc<M, R>> CurriedFunc { get; set; }

        private Expression<Func<T>> Arg1 { get; set; }

        private Expression<Func<T, S>> Arg2 { get; set; }

        private Expression<Func<S, M>> Arg3 { get; set; }

        public override R InvokeResult()
        {
            T argValue1 = this.Arg1.Compile()();

            S argValue2 = this.Arg2.Compile()(argValue1);

            M argValue3 = this.Arg3.Compile()(argValue2);

            R result = FSharpFunc<T, S>.InvokeFast<M, R>(this.Func, argValue1, argValue2, argValue3);

            return result;
        }

        public ICurriedFunction<T, S, M, R> SetResultFunction(Converter<M, R> converter)
        {
            this.ResultFunc = converter;

            this.CurriedFunc = FuncConvert.ToFSharpFunc<S, FSharpFunc<M, R>>(s => this.ResultFunc);

            this.Func = FuncConvert.ToFSharpFunc<T, FSharpFunc<S, FSharpFunc<M, R>>>(t => this.CurriedFunc);

            return this;
        }


        public ICurriedFunction<T, S, M, R> SetArgs(Expression<Func<T>> funcArg1, Expression<Func<T, S>> funcArg2, Expression<Func<S, M>> funcArg3)
        {
            this.Arg1 = funcArg1;
            this.Arg2 = funcArg2;
            this.Arg3 = funcArg3;
            return this;
        }
    }
      
      


The usability is via lambda Expressions



        void testCurried()
        {
            ICurriedFunction<Test, string, double, bool> curry = new CurriedFunction<Test, string, double, bool>();

            curry.SetResultFunction(getBool)
                 .SetArgs(() => getTest(), 
                          (s) => getTestString(s), 
                          (d) => getDouble(d));

            bool result = curry.InvokeResult();
        }       

        Test getTest() => new()
            {
                Id = 1024,
                Text = "Test Real Curry"
            };
		
        string getTestString(Test test) => (test.Id * 4000).ToString();

        double getDouble(string value) => Convert.ToDouble(value);

        bool getBool(double i) =>  i > 50;
                


METHOD SOFTWARE ® 2022

Thursday, July 29, 2021

FSharp : InvokeFast()

Microsoft defines InvokeFast() method to invoke an F# first class function value with two curried arguments. In some cases this will result in a more efficient application than applying the arguments successively
https://github.com/MicrosoftDocs/visualfsharpdocs/blob/master/docs/conceptual/fsharpfunc.invokefast

In this post we implement a basic use of FSharpFunc's InvokeFast, with a curried functions' structure

We begin top-to-bottom, so we first define a FSharpFunc which will takes a string param and will return a double value


              
              FSharpFunc<string, double> doublefunc = FuncConvert.ToFSharpFunc<string, double>((item) => getDouble(item));
              
              //
              
              static double getDouble(string item) => Convert.ToDouble(item);
  
After, we define a FSharpFunc which will takes a parameter type int, and will curry the function just created, with this implementation


  		FSharpFunc<int, FSharpFunc<string, double>> func = FuncConvert
                     .ToFSharpFunc<int, FSharpFunc<string, double>>(i => doublefunc);
  
Now we initialize a variable type int to test the functionality


  
            int o = 2;

            double test = FSharpFunc<int, string>.InvokeFast<double>(func, o, await getString_async(await getNumber_async(o)));  
  
  
<METHOD SOFTWARE 2021 ©>

Sunday, May 24, 2020

F# Experimental: BinaryTree

In this example we write the implementation of a very simple demo of use of FSharpX.Collections.Experimental.BinaryTree<T>

Binary Trees organize in the form of Root and Node(s) in the next way:



Install the Nuget for this demo:



We represent the hierarchy of a Demo class:


        class Demo
        {
            public int Id { get; set; }

            public int? HierarchyId { get; set; }

            public string Text { get; set; }
        }  
        
        // with the next function to get the collection
        
        static IEnumerable<Demo> GetDemoItems(int number)
        {
            for (int i = 0; i <= number; i++)
            {
                yield return new Demo
                {
                    Id = i,
                    Text = $"item{i}",
                    HierarchyId = (i == 0) ? default(int?) : (i < 3) ? 0 : (i < 5) ? 1 : (i < 7) ? 2 : 3
                };
            }
        }        
  


And now we simply build the binary tree structure and iterate over the branches with the print function


        static List<Demo> items;

        static void TestBinaryTree()
        {
            items = GetDemoItems(8).ToList();

            BuildBinaryTree(items);
        }

        static void BuildBinaryTree(List<Demo> items)
        {            
            BinaryTree<Demo> btree = GetBranched(items[0]);
            
            Print(btree);
        }

        static BinaryTree<Demo> GetBranched(Demo item)
        {
            if (item == null)
                return BinaryTree<Demo>.Leaf;

            Demo item1 = items.FirstOrDefault(i => i.HierarchyId == item.Id);

            Demo item2 = items.LastOrDefault(i => i.HierarchyId == item.Id);

            return BinaryTree<Demo>.NewBranch(item, GetBranched(item1), GetBranched(item2));
        }

        static void Print(BinaryTree<Demo> btree)
        {
            if (btree == null)
                return;

            if (btree.IsBranch)
            {
                BinaryTree<Demo>.Branch branch = btree as BinaryTree<Demo>.Branch;

                Console.WriteLine($"Id:{branch.Item1.Id} Text:{branch.Item1.Text}");

                Console.WriteLine("Items:");

                Print(branch.Item2);

                Print(branch.Item3);
            }
            else if (btree.IsLeaf)
            {
                Console.WriteLine("Leaf Tree");
            }
        }  
  
The result is this cmd:


<METHOD SOFTWARE 2020 ©>

Saturday, January 21, 2017

F# : Recursive loops

Recursive functions is one of key concepts of functional programming. F# prefix these functions with keyword rec

In this sample we have defined three functions, two of them recursives, and one of them returning a type int list. The result is the factorization of the number in parameter

Algorithm gets a lot simplified by step in the logic of factorization. This is the algorithm translated to F#



        let divide x s = (x % s) = 0

        let rec lowFactor x s = if (divide x s) then s else lowFactor x (s + 1)

        let rec factorize x =
            [
                if (x <> 1) then

                    let i = lowFactor x 2

                    yield i

                    if (divide x i) then

                        for k in factorize (x / i) do

                            yield k

            ]

        let tst = factorize 108416 


<METHOD SOFTWARE 2020 ©>