14 Replies - 474 Views - Last Post: 07 November 2018 - 09:34 AM

#1 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

How do I write this imperative code in a functional style?

Posted 01 November 2018 - 03:39 PM

How do I write this imperative code in a functional style?

This is my first post here, so please forgive me if this post is off-topic or not suitable. I am an experienced OO/imperative coder in C#, trying to learn functional programming. I've read lots of books, watched lots of videos, etc, and have the basic idea, but am having trouble seeing how to put it all together. I would be interested to see how a real life use case would look in FP.

We have an account with a third party system that supplies survey software. We create survery requests based on tickets in our database, send a message to their API, people fill in the surveys, and we use another API call to download the responses and update our database. We download an array of responses, and each response contains a number of answers. All answers are strings, but some need to be converted to ints, DateTimes, etc.

All questions are optional, and we have to validate the data. If we encounter missing data or invalid data, we carry on, but need to log the issues.

Simplified C# code for the process would look something like this...

  foreach (var r in responses) {
    var ticket = ticketDatabase.Get(r.TicketID);
    string errors = "";
    if (ticket != null) {
      try {
        ticket.a1 = FindIntAnswer(r, Question1ID);
      } catch (Exception ex) {
        errors += "Q1: " + ex.Message;
      }
      try {
        ticket.a2 = FindStringAnswer(r, Question2ID);
      } catch (Exception ex) {
        errors += "Q2: " + ex.Message;
      }
      // Repeat for every question...
      if (errors != "") {
         Log.Debug("Errors for ticket " + ticket.ID + " - " + errors);
      }
      ticketDatabase.Save(ticket);
    } else {
      errors = "Ticket " + ticket.ID + " not found";
    }
    Log(errors);
  }



There are similar methods for other data types. As you can see, very repetitive and imperative.

Question1ID, Question2ID etc are constant ints in a helper class. In the real code, the names are far more descriptive, as are the property names on the ticket object.

I have been using LanguageExt in my FP experiments, and managed to make this a wee bit more functional by writing code like this...

Try(() => FindIntAnswer(r, Question1ID))
  .Match(
    s => ticket.a1 = s,
    e => errors += e);



However, this is really still imperative code. My main problem here is that I seem to need to handle each question individually, so don't get the flow of data from function to function that seems to be a mark of FP.

How would I write such code in a purely FP style?

Is This A Good Question/Topic? 0
  • +

Replies To: How do I write this imperative code in a functional style?

#2 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7401
  • View blog
  • Posts: 15,338
  • Joined: 16-October 07

Re: How do I write this imperative code in a functional style?

Posted 02 November 2018 - 07:56 AM

There's simply not enough here to get rolling...

Still, what the hell: challenge accepted.

First some, scaffolding
public abstract class Foo {
    public interface Response {
        int TicketID { get; }
    }
    public interface TicketDb {
        Ticket Get(int ticketId);
        void Save(Ticket ticket);
    }
    public interface Ticket {
        int ID { get; }
        int a1 { get; set; }
        string a2 { get; set; }
    }
    int Question1ID { get; }
    int Question2ID { get; }
    public abstract int FindIntAnswer(Response r, int id);
    public abstract string FindStringAnswer(Response r, int id);
    protected abstract string LogDebug(string msg);
    protected abstract string Log(string msg);

    void Bar(IEnumerable<Response> responses, TicketDb ticketDatabase) {
        foreach (var r in responses) {
            var ticket = ticketDatabase.Get(r.TicketID);
            string errors = "";
            if (ticket != null) {
                try {
                    ticket.a1 = FindIntAnswer(r, Question1ID);
                } catch (Exception ex) {
                    errors += "Q1: " + ex.Message;
                }
                try {
                    ticket.a2 = FindStringAnswer(r, Question2ID);
                } catch (Exception ex) {
                    errors += "Q2: " + ex.Message;
                }
                // Repeat for every question...
                if (errors != "") {
                    LogDebug("Errors for ticket " + ticket.ID + " - " + errors);
                }
                ticketDatabase.Save(ticket);
            } else {
                errors = "Ticket " + ticket.ID + " not found";
            }
            Log(errors);
        }
    }
}



Within that context, something a little more functiony might look like:
    void Baz(IEnumerable<Response> responses, TicketDb ticketDatabase) {
        Log(string.Join("\n", responses.Select(r => ProcessTicket(r, ticketDatabase.Get(r.TicketID))).Where(x => x != null)));

        IEnumerable<Func<Ticket, string>> GetQuestions(Response r) {
            yield return WrapError("Q1", (ticket) => ticket.a1 = FindIntAnswer(r, Question1ID));
            yield return WrapError("Q2", (ticket) => ticket.a2 = FindStringAnswer(r, Question2ID));
            // Repeat for every question...
        }

        Func<Ticket, string> WrapError(string questionName, Action<Ticket> call) {
            return (ticket) => {
                try {
                    call(ticket);
                    return null;
                } catch (Exception ex) {
                    return questionName + ": " + ex.Message;
                }
            };
        }

        string FinalizeTicket(Ticket ticket, IEnumerable<string> errors) {
            if (errors.Any()) {
                return "Errors for ticket " + ticket.ID + " - " + errors;
            } else {
                ticketDatabase.Save(ticket);
                return null;
            }
        }

        string ProcessTicket(Response r, Ticket ticket) => (ticket == null)
            ? $"Ticket {r.TicketID} not found"
            : FinalizeTicket(ticket, GetQuestions(r).Select(call => call(ticket)).Where(x => x != null));
    }



Hope this helps.
Was This Post Helpful? 1
  • +
  • -

#3 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 02 November 2018 - 08:46 AM

Thanks for the reply. I'm not at a computer now, so won't be able to try it, but if you can tell me what extra info you need, I'll be glad to supply if that would help you answer.

Thanks again.
Was This Post Helpful? 0
  • +
  • -

#4 ndc85430   User is online

  • I think you'll find it's "Dr"
  • member icon

Reputation: 972
  • View blog
  • Posts: 3,839
  • Joined: 13-June 14

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 01:34 PM

Have you thought about Option (Maybe) and Result monads? I had a whole post written, but I'm not sure how much of it is useful.
Was This Post Helpful? 0
  • +
  • -

#5 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 01:46 PM

View Postndc85430, on 06 November 2018 - 01:34 PM, said:

Have you thought about Option (Maybe) and Result monads?


I had thought about Option, but wasn't sure how useful it would be here. It was more the overall structure I was trying to work out, hadn't got too far into the details.

Not come across the Result monad, what is that for?

View Postndc85430, on 06 November 2018 - 01:34 PM, said:

I had a whole post written, but I'm not sure how much of it is useful.


Can only try! At my stage, anything that explains FP is useful

Thanks for th ereply.
Was This Post Helpful? 0
  • +
  • -

#6 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 01:57 PM

View Postbaavgai, on 02 November 2018 - 07:56 AM, said:

There's simply not enough here to get rolling...


Hee hee, still amused at that comment, given that you followed it with such an excellent post!

Anyway, I had a closer look at the code, and I can see what you've done. My only question is how much benefit there is in this approach. I'm not being rude by the way, I'm trying to understand.

I can see that with the usual standard examples that a nice flow of extension methods makes for much cleaner code than a whole load of if, for/foreach etc statements, but in this case, it doesn't look quite so clean.

However, I do like the way you wrapped all of the code to get the answers and update the ticket in a sequence of yield return, as you end up with a collection that's easy to handle.

Could just be my lack of familiarity with FP, but I think the imperative code was cleaner.

Any comments? Thanks again for the excellent reply.
Was This Post Helpful? 0
  • +
  • -

#7 ndc85430   User is online

  • I think you'll find it's "Dr"
  • member icon

Reputation: 972
  • View blog
  • Posts: 3,839
  • Joined: 13-June 14

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 02:10 PM

Remember that one of the ideas in FP is that functions are pure, that is that they don't have side effects and can only return values. Naturally, some computations can fail and throwing exceptions goes against this. So. Result is a type that represents a computation that can succeed or fail. In Scala, one uses either Try or Either to model this. In either case (no pun intended!), each type has two subtypes: for Try it's Success[T] and Failure[U] and for Either, it's Left[U] and Right[T], where the T and U are generic type parameters. Since they're monads, you can map and flatMap on them (well, I'm sure that's not particularly the definition of a monad, but meh).

Your case looks a bit more complicated, though. I'm wondering if you really need an applicative or something.
Was This Post Helpful? 0
  • +
  • -

#8 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 02:18 PM

View Postndc85430, on 06 November 2018 - 02:10 PM, said:

Remember that one of the ideas in FP is that functions are pure, that is that they don't have side effects and can only return values.


That's one thing that concerned me (if that's the right word) about baavgai's code (although I forgot to mention this when replying), is that the code inside GetQuestions isn't pure, it's mutating the ticket. Now I don't see how we get around that, other than creating a copy of the ticket to return, but as this is an object graph pulled from an Entity Framework model, I think that would cause more problems that it would solve.

View Postndc85430, on 06 November 2018 - 02:10 PM, said:

Naturally, some computations can fail and throwing exceptions goes against this. So. Result is a type that represents a computation that can succeed or fail. In Scala, one uses either Try or Either to model this. In either case (no pun intended!), each type has two subtypes: for Try it's Success[T] and Failure[U] and for Either, it's Left[U] and Right[T], where the T and U are generic type parameters. Since they're monads, you can map and flatMap on them (well, I'm sure that's not particularly the definition of a monad, but meh).


Ah, I'm familiar with Try and Either, I just hadn't heard them called Result before. One thing I'm learning about FP is how many different names there are for the same thing!

View Postndc85430, on 06 November 2018 - 02:10 PM, said:

Your case looks a bit more complicated, though. I'm wondering if you really need an applicative or something.


Please could you elaborate? I'm open to anything here!

Thanks again
Was This Post Helpful? 0
  • +
  • -

#9 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7401
  • View blog
  • Posts: 15,338
  • Joined: 16-October 07

Re: How do I write this imperative code in a functional style?

Posted 06 November 2018 - 05:25 PM

View PostYossu, on 06 November 2018 - 03:57 PM, said:

My only question is how much benefit there is in this approach.

This is a fair question. Honestly, going from a strict transcription, maybe not so much. A functional language demands a more functional approach, else your just doing really awkward imperative code.

So, if is not necessarily verboten in functional programming. However, in a functional style you'll usually see that an if requires else: a function should always return a result, even if that result is null. Curiously, if you use a functional language, like F#, the Option type is mapped to the .NET null.

Hmm... in F#:
type Response = int // it's unclear what response is, in context, so we'll just use a number

type Ticket = int  // it's unclear what ticket is, in context, so we'll just use a number

type QuestionType = IntAnswer | StringAnswer

type QuestionId = int

type Question = QuestionId * string * QuestionType

type Questions = Question list

type AnswerType = 
    | AnsInt of int
    | AnsStr of string
    | Fail of string

type FinalTicket = Ticket * (AnswerType list)

let question id name qt: Question = (id,name,qt)

// current dummy implementions
// implement later
let ticketFromDb (r:Response): Ticket = 0
let ticketToDb (x:FinalTicket) = ()
let findAnswer (r:Response) (q:Question) = Fail("needs implementation")

let processResponse (qs:Questions) r =
    qs |> List.map (findAnswer r)

let processQuestions =
    [
    question 1 "Q1" QuestionType.IntAnswer
    question 2 "Q2" QuestionType.StringAnswer
    ] |> processResponse




The REPL output, so you can see the inferred types:
type Response = int
type Ticket = int
type QuestionType =
  | IntAnswer
  | StringAnswer
type QuestionId = int
type Question = QuestionId * string * QuestionType
type Questions = Question list
type AnswerType =
  | AnsInt of int
  | AnsStr of string
  | Fail of string
type FinalTicket = Ticket * AnswerType list
val question : id:QuestionId -> name:string -> qt:QuestionType -> Question
val ticketFromDb : r:Response -> Ticket
val ticketToDb : Ticket * AnswerType list -> unit
val findAnswer :
  r:Response -> QuestionId * string * QuestionType -> AnswerType
val processResponse : qs:Questions -> r:Response -> AnswerType list
val processQuestions : (Response -> AnswerType list)



Your normal C# classes and collection are inherently mutable. Functional languages are inherently immutable. Rather than an object's property changing via processing, you'll tend to see objects transforming into new objects over the course of function calls. It's a different way to look at the problem and any very direct transliteration probably isn't demonstrating advantage of the either side, as you simply don't approach the problems in exactly the same way.
Was This Post Helpful? 1
  • +
  • -

#10 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 04:44 AM

View Postbaavgai, on 06 November 2018 - 05:25 PM, said:

View PostYossu, on 06 November 2018 - 03:57 PM, said:

My only question is how much benefit there is in this approach.

This is a fair question. Honestly, going from a strict transcription, maybe not so much. A functional language demands a more functional approach, else your just doing really awkward imperative code.


That's my problem, I don't seem to be able to see how a case like this can be done functionally. My attempt at this was still fairly imperative. I only showed the imperative code to give you an idea of what I as doing (sometimes a few lines of codes says more than a whole load of words).

How would you approach such a situation? Ignore my imperative code, and imagine you were having to write code for this. I'd like to see what "real" FP code would look.

View Postbaavgai, on 06 November 2018 - 05:25 PM, said:

Your normal C# classes and collection are inherently mutable. Functional languages are inherently immutable. Rather than an object's property changing via processing, you'll tend to see objects transforming into new objects over the course of function calls.


I know, but as I mentioned in my reply to ndc85430, I'm not sure how well that would work here. I'm dealing with an object that was pulled from an Entity Framework model, that has loads of navigation properties hanging off it. Making a copy of the whole object graph every time we change one property would be a major pain, involve lots of code and would likely be quite error-prone.

This is one of the areas I'm struggling with thinking functionally. I can see how it makes sense to pass a copy of your object back when you are dealing with a simple, single object (like all the books and blog articles use), but I have yet to see how you do this when you're dealing with something more realistic - at least in my experience. It's that leap from simple examples to the Real World™ that I'm missing.

Could be that real FPers don't use things like EF. If so, I need to understand how it should be done in a way that gives you clean robust code. I saw one book where he insisted on using raw SQL for everything, which really put me off. We've come a long way since those days, and I would find it hard to believe that an approach such as FP, which emphasises clean and clear code would require embedded SQL.

View Postbaavgai, on 06 November 2018 - 05:25 PM, said:

It's a different way to look at the problem and any very direct transliteration probably isn't demonstrating advantage of the either side, as you simply don't approach the problems in exactly the same way.


As I said above, maybe you could explain to me how you would approach this problem from a purely FP perspective. That's what I'm trying to learn!

Thanks again for all the help.
Was This Post Helpful? 0
  • +
  • -

#11 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7401
  • View blog
  • Posts: 15,338
  • Joined: 16-October 07

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 05:51 AM

I guess the real question is what are you expecting to get from an "FP" style? Because, dirty little secret time, it may not be what you expect.

Your example has a lot of IO, i.e. mutable state. You are probably getting user input, you're using EF objects and presumably a DbContext. In such an environment, anything FP would be fundamentally stylistic, as you're still bound to OO models not matter what you do.

So, let's roll back a bit. If you were to drink the OOP koolaid, you'd see all problem spaces as clean, self describing, object entities. But problems are messier than that and, sometimes, you'll find that you're wedging objects and classes into things simply to be more "object oriented" without gaining anything for your efforts.

An FP analog is similar. In Pure Functional Programming land, all problems can be expressed and solved with functions. Even data can be a function or vice versa: lambda to the max. Mutability and exceptions are the bane of this vision and yet most programs will have these.

Haskell is a good example of where FP gets messy. The code in terse, functional, expressive, side effect free, PURE. But real world problems exist outside that domain, so the minute you throw in something like an IO monad, it's like you've pissed in the punch bowl and all your expressive elegance is irreparably befouled.

So, in C#, learn Linq. Linq comes from an functional programming sensibility. When you can replace a loop with a map, the FP gods smile.

If you want to learn how to program functionally, write some programs using functional languages. Solve some programming challenges. Then, come back to what you're working on with new eyes.
Was This Post Helpful? 1
  • +
  • -

#12 andrewsw   User is offline

  • Stealth IT
  • member icon

Reputation: 6746
  • View blog
  • Posts: 27,776
  • Joined: 12-December 12

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 08:08 AM

I'll post this useful link (although the OP may have encountered it already)

So You Want to be a Functional Programmer
Was This Post Helpful? 1
  • +
  • -

#13 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 08:51 AM

View Postandrewsw, on 07 November 2018 - 08:08 AM, said:

I'll post this useful link (although the OP may have encountered it already)

So You Want to be a Functional Programmer


Thanks for the link, it looks very good. I have read a lot about FP, and am on my 3rd time through Enrico Buonanno's excellent book in FP in C#, so most of what I read in the parts of that link I saw so far were familiar.

My main problem is moving from the simple examples they show in such articles and books to more complex ones like I described here. The only way I can think of solving this problem is imperatively, which is why I came here to see if anyone could show me an FP way.

Thanks again.
Was This Post Helpful? 0
  • +
  • -

#14 andrewsw   User is offline

  • Stealth IT
  • member icon

Reputation: 6746
  • View blog
  • Posts: 27,776
  • Joined: 12-December 12

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 09:04 AM

You could perhaps start with a version that does not involve the distraction of Entity Framework
- but I am not a person to advise (anyone) about FP ;)
Was This Post Helpful? 0
  • +
  • -

#15 Yossu   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 01-November 18

Re: How do I write this imperative code in a functional style?

Posted 07 November 2018 - 09:34 AM

View Postandrewsw, on 07 November 2018 - 09:04 AM, said:

You could perhaps start with a version that does not involve the distraction of Entity Framework


yeah, problem is that all the interesting stuff seems to come when you move to this kind of problem. I've followed through a lot of the simple examples in the books, blogs, etc. I can see how that's done. It's when you get on to this sort of stuff that I get stuck.

View Postandrewsw, on 07 November 2018 - 09:04 AM, said:

- but I am not a person to advise (anyone) about FP ;)/>

Don't do yourself down!

Thanks for th ereply
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1