Functional programming compared to OOP with classes

I have been interested in some of the concepts of functional programming lately. I have used OOP for some time now. I can see how I would build a fairly complex app in OOP. Each object would know how to do things that object does. Or anything it’s parents class does as well. So I can simply tell Person().speak() to make the person talk.

But how do I do similar things in functional programming? I see how functions are first class items. But that function only does one specific thing. Would I simply have a say() method floating around and call it with an equivalent of Person() argument so I know what kind of thing is saying something?

So I can see the simple things, just how would I do the comparable of OOP and objects in functional programming, so I can modularize and organize my code base?

For reference, my primary experience with OOP is Python, PHP, and some C#. The languages that I am looking at that have functional features are Scala and Haskell. Though I am leaning towards Scala.

Basic Example (Python):

Animal(object):
    def say(self, what):
        print(what)

Dog(Animal):
    def say(self, what):
        super().say('dog barks: {0}'.format(what))

Cat(Animal):
    def say(self, what):
        super().say('cat meows: {0}'.format(what))

dog = Dog()
cat = Cat()
dog.say('ruff')
cat.say('purr')

14

What you are really asking about here is how to do Polymorphism in functional languages, i.e. how to create functions that behave differently based on their arguments.

Note the first argument to a function is typically equivalent to the “object” in OOP, but in functional languages you usually want to separate functions from data, so the “object” is likely to be a pure (immutable) data value.

Functional languages in general provide various options for achieving polymorphism:

  • Something like multimethods which call a different function based on examining the arguments provided. This can be done on the type of the first argument (which is effectively equal to the behaviour of most OOP languages), but could also be done on other attributes of the arguments.
  • Prototype / object-like data structures which contain first-class functions as members. So you could embed a “say” function inside your dog and cat data structures. Effectively you have made the code part of the data.
  • Pattern matching – where pattern matching logic is built into the function definition, and ensures different behaviours for different parameters. Common in Haskell.
  • Branching / conditions – equivalent to if / else clauses in OOP. Might not be highly extensible, but can still be appropriate in many cases when you have a limited set of possible values (e.g. was the function passed a number or a string or null?)

As an example, here’s a Clojure implementation of your problem using multimethods:

;; define a multimethod, that dispatched on the ":type" keyword
(defmulti say :type)  

;; define specific methods for each possible value of :type. You can add more later
(defmethod say :cat [animal what] (println (str "Car purrs: " what)))
(defmethod say :dog [animal what] (println (str "Dog barks: " what)))
(defmethod say :default [animal what] (println (str "Unknown noise: " what)))

(say {:type :dog} "ruff")
=> Dog barks: ruff

(say {:type :ape} "ook")
=> Unknown noise: ook

Note that this behaviour doesn’t require any explicit classes to be defined: regular maps work fine. The dispatch function (:type in this case) could be any arbitrary function of the arguments.

1

This is not a direct answer, nor is it necessarily 100% accurate as I’m not a functional language expert. But in either case, I’ll share with you my experience…

About a year ago I was in a similar boat as you. I’ve done C++ and C# and all of my designs were always very heavy on OOP. I’ve heard about FP languages, read some info online, flipped through F# book but still couldn’t really grasp how can an FP language replace OOP or be useful in general as most examples I’ve seen were just too simple.

For me the “breakthrough” came when I decided to learn python. I downloaded python, then went to project euler homepage and just started doing one problem after another. Python is not necessarily an FP language and you can certainly create classes in it, but compared to C++/Java/C#, it does have a lot more of FP constructs, so when I started playing with it, I made a conscious decision not to define a class unless I absolutely had to.

What I found interesting about Python was how easy and natural it was to take functions and “stitch” them to create more complex functions and in the end your problem was still solved by calling a single function.

You pointed out that when coding you should follow single responsibility principle and that is absolutely correct. But just because function is responsible for a single task, doesn’t mean it can only do the absolute bare minimum. In FP, you still have abstraction levels. So your higher-level functions can still do “one” thing but they can delegate to lower level functions to implement finer details of how that “one” thing is achieved.

The key with FP however is that you do not have side-effects. As long as you treat the application as simple data transformation with defined set of inputs and set of outputs, you can write FP code that would accomplish what you need. Obviously not every application will fit nicely into this mold, but once you start doing it, you’ll be surprised how many applications do fit. And this is where I think Python, F# or Scala shine because they give you FP constructs but when you do need to remember your state and “introduce side-effects” you can always fall back on true and tried OOP techniques.

Since then, I’ve written a whole bunch of python code as utilities and other helper scripts for internal work and some of them scaled out fairly far but by remembering basic SOLID principles, most of that code still came out very maintainable and flexible. Just like in OOP your interface is a class and you move classes around as you refactor and/or add functionality, in FP you do exactly same thing with functions.

Last week I started coding in Java and since then, almost on daily basis I get reminded that when in OOP, I have to implement interfaces by declaring classes with methods that override functions, in some cases I could achieve the same thing in Python using a simple lambda expression, for example, 20-30 lines of code that I wrote to scan a directory, would’ve been 1-2 lines in Python and no classes.

FP themselves are higher level languages. In Python (sorry, my only FP experience) I could put together list comprehension inside another list comprehension with lambdas and other stuff thrown in and the whole thing would only be 3-4 lines of code. In C++, I could absolutely accomplish the same thing, but because C++ is lower-level, I would have to write much more code than 3-4 lines and as the number of lines increases, my SRP training would kick in and I would start thinking about how to split up code into smaller pieces (i.e. more functions). But in the interests of maintainability and hiding implementation details, I would put all those functions into the same class and make them private. And there you have it… I just created a class whereas in python I would have written “return (…. lambda x:.. ….)”

4

In Haskell, the closest you have is “class”. This class though not as same as the class in Java and C++ , will work for what you want in this case.

In your case this is how your code will look.

class Animal a where 
say :: String -> sound 

Then you can have individual data types adapting these methods.

instance Animal Dog where
say s = "bark " ++ s 

EDIT :-
Before you can specialize say for Dog you need to tell the system that Dog is animal.

data Dog =  --something here -- (deriving Animal)

EDIT :- For Wilq.
Now if you want to use say in a function say foo, you will have to tell haskell that foo can only work with Animal.

foo :: (Animal a) => a -> String -> String
foo a str = say a str 

now if you call foo with dog it will bark, if you call with cat it will meow.

main = do 
let d = dog (--cstr parameters--)
    c = cat  
in show $ foo d "Hello World"

You now can not have any other definition of function say. If say is called with anything which is not animal, it will cause compile error.

3

Functional languages use 2 constructs to achieve polymorphism:

  • First order functions
  • Generics

Creating polymorphic code with those is completely different than how OOP uses inheritance and virtual methods. While both of those might be available in your favorite OOP language (like C#), most functional languages (like Haskell) kick it up to eleven. It is rare to function to be non-generic and most functions have functions as parameters.

It is hard to explain like this and it will require lot of your time to learn this new way. But to do this, you need to completely forget OOP, because that’s not how it works in functional world.

9

it really depends on what you want to accomplish.

if you just need a way to organize behaviour based on selective criteria, you can use e.g. a dictionary (hash-table) with function-objects. in python it could be something along the lines of:

def bark(what):
    print "barks: {0}".format(what) 

def meow(what):
    print "meows: {0}".format(what)

def climb(how):
    print "climbs: {0}".format(how)

if __name__ == "__main__":
    animals = {'dog': {'say': bark},
               'cat': {'say': meow,
                       'climb': climb}}
    animals['dog']['say']("ruff")
    animals['cat']['say']("purr")
    animals['cat']['climb']("well")

note however, that (a) there are no ‘instances’ of dog or cat and (b) you will have to keep track of the ‘type’ of your objects yourself.

like for example: pets = [['martin','dog','grrrh'], ['martha', 'cat', 'zzzz']]. then you could do a list comprehension like [animals[pet[1]]['say'](pet[2]) for pet in pets]

OO Languages can be used in place of low-level languages sometimes to interface directly with a machine. C++ For sure, but even for C# there are adapters and such. Though writing code to control mechanical parts and have minute control over memory are best kept as close to low-level as possible. But if this question is related to current Object-Oriented software like Line Of Business, web applications, IOT, Web Services, and the majority of mass used applications, then…

Answer, if applicable

Readers might try working with a Service-Oriented Architecture (SOA). That is, DDD, N-Layered, N-Tiered, Hexagonal, whatever. I haven’t seen a Large business application efficiently use “Traditional” OO (Active-Record or Rich-Models) as it was described in the 70’s and 80’s very much in the last decade+. (See Note 1)

The fault isn’t with the OP, but there are a couple problems with the question.

  1. The example you provide is simply to demonstrate Polymorphism, it isn’t production code. Sometimes examples exactly like that are taken literally.

  2. In FP and SOA, Data is separated from Business Logic. That is, Data and Logic don’t go together. Logic goes into Services, and Data (Domain Models) does not have Polymorphic behavior (See Note 2).

  3. Services and Functions can be Polymorphic. In FP, you frequently pass functions as parameters to other functions instead of values. You can do the same in OO Languages with types like Callable or Func, but it doesn’t run rampant (See Note 3). In FP and SOA, your Models aren’t Polymorphic, only your Services/Functions. (See Note 4)

  4. There is a bad case of hardcoding in that example. I’m not only talking about the red colored string “dog barks”. I’m also talking about the CatModel and DogModel themselves. What happens when you want to add a Sheep? You have to go into your code and create new code? Why? In production code, I would rather see just an AnimalModel with its properties. At worst, an AmphibianModel and a FowlModel if their properties and handling are so different.

This is what I’d expect to see in a current “OO” Language:

public class Animal
{
    public int AnimalID { get; set; }
    public int LegCount { get; set; }
    public string Name { get; set; }
    public string WhatISay { get; set; }
}

public class AnimalService : IManageAnimals
{
    private IPersistAnimals _animalRepo;
    public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }

    public List<Animal> GetAnimals() => _animalRepo.GetAnimals();

    public string WhatDoISay(Animal animal)
    {
        if (!string.IsNullOrWhiteSpace(animal.WhatISay))
            return animal.WhatISay;

        return _animalRepo.GetAnimalNoise(animal.AnimalID);
    }
}

How do you move from Classes in OO to Functional Programming? As others have said; You can, but you don’t really. The point of the above is to demonstrate that you shouldn’t even be using Classes (in the traditional sense of the world) when doing Java and C#. Once you get to writing code in a Service-Oriented Architecture (DDD, Layered, Tiered, Hexagonal, whatever), you’ll be one step closer to Functional because you separate your Data (Domain Models) From your Logical Functions (Services).

OO Language one step closer to FP

You might even take it a bit further and split your SOA Services into two types.

Optional Class Type 1: Common Interface-Implementing Services for Entry Points. These would be “impure” Entry-Points which can call into “Pure” or “Impure” other functionality. This might be your Entry Points from a RESTful API.

Optional Class Type 2: Pure Business Logic Services. These are Static Classes which have “Pure” functionality. In FP, “Pure” means there are no side effects. It doesn’t explicitly set State or Persistence anywhere. (See Note 5)

So when you think of Classes in Object-Oriented Languages, being used in a Service-Oriented Architecture, it not only benefits your OO Code, it begins to make Functional Programming seem very easy to understand.

Notes

Note 1: Original “Rich” or “Active-Record” Object-Oriented Design is still around. There’s a LOT of legacy code like that back when people were “doing it right” a decade or more ago. Last time I saw that kind of code (done correctly) was from an video game Codebase in C++ Where they were controlling memory precisely and had very limited space. Not to say FP and Service-Oriented Architectures are beasts and shouldn’t consider hardware. But they place the ability to constantly change, be maintained, have variable data sizes, and other aspects as priority. In video games and machine AI, you control the signals and data very precisely.

Note 2: Domain Models do not have Polymorphic Behavior, nor do they have External Dependencies. They are “Isolated”. That doesn’t mean they have to be 100% Anemic. They can have a lot of logic related to their construction and mutable property alteration, if such applies. See DDD “Value Objects” and Entities by Eric Evans and Mark Seemann.

Note 3: Linq and Lambda’s are very common. But when a user creates a new function, they rarely use Func or Callable as parameters, whereas in FP it would be weird to see an app without functions following that pattern.

Note 4: Not confusing Polymorphism with Inheritance. A CatModel might inherit AnimalBase to determine which Properties an Animal typically has. But as I show, Models like this are a Code Smell. If you see this pattern, you might consider breaking it down and turning it into data.

Note 5: Pure functions can (and do) accept functions as parameters. The incoming function might be impure, but might be pure. For testing purposes, it would always be pure. But in production, though it is treated as pure, it might contain side-effects. That doesn’t change the fact that the pure function is pure. Though the parameter function might be impure. Not confusing! 😀

You could do something like this .. php

    function say($whostosay)
    {
        if($whostosay == 'cat')
        {
             return 'purr';
        }elseif($whostosay == 'dog'){
             return 'bark';
        }else{
             //do something with errors....
        }
     }

     function speak($whostosay)
     {
          return $whostosay .''s '.say($whostosay);
     }
     echo speak('cat');
     >>>cat's purr
     echo speak('dog');
     >>>dogs's bark

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật