Introduction to Functional Programming in F# – Part 5

Datum

11.10.2022

content.autor.writtenBy

Ian Russel

Introduction

Welcome to the fifth post in this introductory series on Functional Programming in F#. In this post we will be building upon some of the concepts we have learned in previous posts whilst investigating functional collections.

Before We Start

We are going to use the solution we created in the last post of this series: https://trustbit.tech/blog/2019/10/01/introduction-to-functional-programming-in-f-sharp-part-4.

Add Orders.fs, OrderTests.fsx and lists.fsx to the code project and OrderTests.fs to the test project.

The Basics

F# has a hugely deserved reputation for being great for data-centric use cases like finance and data science due in a large part to the power of it's support for data structures and collection handling. In this post we will look at how we can harness some of this power in normal line of business apps.

There are a number of collections in F# that we can make use of but the three primary ones are:

  • Sequence (Seq) - Lazily evaluated - Equivalent to IEnumerable.

  • Array - Great for numerics/data science. There are built-in modules for 2d, 3d and 4d arrays.

  • List - Eagerly evaluated and immutable structure and data. F# specific, not same as List.

Each of these types has a module that contains a wide range of functions including some to convert to/from each other.

In this post we are going to concentrate on the List type and module.

Core Functionality

We will be using lists.fsx for this section. Remember to highlight the code and run it in F# Interactive (FSI).

Create an empty list:

let items = []

Create a list with five integers:

let items = [1;2;3;4;5]

In this case, we could also do this:

let items = [1..5]

Or we could use a List comprehension:

let items = [ for x in 1..5 do yield x ]

List comprehensions are really powerful but we are not going to use them in this post.

To add an item to a list, we use the cons operator:

let items' = 6 :: items

The original list remains unaffected by the new item as it is immutable.

A list is made up of a head (single item) and a tail (list of items). We can pattern match on a list to show this:

let readList items =
    match items with
    | [] -> sprintf "Empty list"
    | head :: tail -> sprintf "Head: %A and Tail: %A" head tail

let emptyList = readList [] // "Empty list"
let multipleList = readList [1;2;3;4;5] // "Head: 1 and Tail: 
[2;3;4;5]"
let singleItemList = readList [1] // "Head: 1 and Tail: []"

We can join (concatenate) two lists together:

let list1 = [1..5]
let list2 = [3..7]
let emptyList = []

let joined = list1 @ list2 // [1;2;3;4;5;3;4;5;6;7]
let joinedEmpty = list1 @ emptyList // [1;2;3;4;5]
let emptyJoined = emptyList @ list1 // [1;2;3;4;5]

As lists are immutable, we can re-use them knowing that there values/structure will never change.

We could also use the concat function on the List module to do the same job as the @ operator:

let joined = List.concat [list1;list2]

We can filter a list using an ('a -> bool) function and the filter function from the List module:

let myList = [1..9]

let getEvens items =
    items
    |> List.filter (fun x -> x % 2 = 0)

let evens = getEvens myList // [2;4;6;8]

We can add up the items in a list using the sum function:

let sum items =
    items |> List.sum

let mySum = sum myList // 45

Other aggregation functions are as easy to use but we are not going to look at them here.

Sometimes we want to perform an operation on each item in a list. If we want to return the new list, we use the map function:

let triple items =
    items
    |> List.map (fun x -> x * 3)

let myTriples = triple myList

If we don't want to return a new list, we use the iter function:

let print items =
    items
    |> List.iter (fun x -> (sprintf "My value is %i" x))

print myList |> ignore

Let's take a look at a more complicated example using map that changes the structure of the output list. We will use a list of tuples (int * decimal) which might represent quantity and unit price.

let items = [(1,0.25M);(5,0.25M);(1,2.25M);(1,125M);(7,10.9M)]

To calculate the total price of the items, we can use map to convert (int * decimal) list to decimal list and then sum the items:

let sum items =
    items
    |> List.map (fun (q, p) -> decimal q * p)
    |> List.sum

Note the explicit conversion of the integer to a decimal. F# is strict about types in calculations and does support implicit conversion. In this particular case, there is an easier way to do the calculation in one step:

let sum items =
    items
    |> List.sumBy (fun (q, p) -> decimal q * p)

Folding

A very powerful functional concept that we can use to do similar aggregation tasks (and lots more that we won't cover) is the fold function:

let total items =
    items
    |> List.fold (fun acc (q, p) -> acc + decimal q * p) 0M

let total = getTotal items

The lambda function uses an accumulator and the deconstructed tuple and simply adds the intermediate calculation to the accumulator. The 0M parameter is the initial value of the accumulator. If we were folding using multiplication, the initial value would probably have been 1M.

To make it clearer what we are trying to do, we could use the ||> operator:

let getTotal items =
    (0M, items) ||> List.fold (fun acc (q, p) -> acc + 
decimal q * p)

Grouping Data and Uniqueness

Rather than try to explain what the groupBy function does, it will be easier to show you:

let myList = [1;2;3;4;5;7;6;5;4;3]    

let groupBy items = // 'a list -> ('a * 'a list) list
    items
    |> List.groupBy (fun x -> x)

let gbResult = groupBy myList // [1,[1];2,[2];3,[3;3];
4,[4;4];5,[5;5];6,[6];7,[7]]

To get the list of unique items from the result list, we can use the map function:

let unique items =
    items
    |> groupBy // or List.groupBy (fun x -> x)
    |> List.map (fun (i, _) -> i)

let unResult = unique myList // [1;2;3;4;5;6;7]

There is a built-in collection type called Set that will do this as well:

let uniqueSet items =
    items
    |> Set.ofList

let setResult = uniqueSet myList // [1;2;3;4;5;6;7]

Note the use of the ofList function to convert a list to a set.

We now have enough information to move onto a practical example of using an F# list.

Practical Example

In this example code we are going to manage an order with an immutable list of items. The functionality we need to add is:

  • Add an item

  • Remove an item

  • Reduce quantity of an item

  • Clear all of the items

First, create a module called Orders in Orders.fs and add record types for Order and Order Item:

type Item = {
    ProductId : int
    Quantity : int
}

type Order = {
    Id : int
    Items : Item list
}

Now we need to add a function to add an item to the order. This function needs to cater for products that exist in the order as well as those that don't. Let's create a couple of helpers bindings to help us get started:

let order = { Id = 1; Items = [ {ProductId = 1; Quantity = 1}]}
let newItem = { ProductId = 1; Quantity = 1 }

Firstly we need to group the items by the productId:

let addItem item order = // Item -> Order -> 
(int * Item list) list
    let items = 
        item :: order.Items
        |> List.groupBy (fun i -> i.ProductId)

let result = addItem newItem order // [(1,[ 
{ ProductId = 1; Quantity = 1 };
{ ProductId = 1; Quantity = 1 } ])]

Then we use the map and sumBy functions to aggregate per product:

let addItem item order = // Item -> Order -> Item list
    let items = 
        item :: order.Items
        |> List.groupBy (fun i -> i.ProductId) 
// (int * Item list) list
        |> List.map (fun (id, items) -> 
{ ProductId = id; Quantity = items |> 
List.sumBy (fun i -> i.Quantity) })

let result = addItem newItem order // [ 
{ ProductId = 1; Quantity = 2 } ]

Finally, we need to copy and update the order with our newly calculated items:

let addItem item order = // Item -> Order -> Order
    let items = 
        item :: order.Items
        |> List.groupBy (fun i -> i.ProductId) 
// (int * Item list) list
        |> List.map (fun (id, items) -> 
{ ProductId = id; Quantity = items |> List.sumBy 
(fun i -> i.Quantity) })
    { order with Items = items }

let result = addItem newItem order 
// { Id = 1; Items = [ { ProductId = 1; Quantity = 2 } ] }

Remove the helpers for order, newItem and result as we are going to create the following asserts in the OrderTests.fsx file:

let addNewItemAssert = 
    let myEmptyOrder = { Id = 1; Items = [] }
    let expected = { Id = 1; Items = [ 
{ ProductId = 1; Quantity = 1 } ] }
    let actual = myEmptyOrder |> addItem { 
ProductId = 1; Quantity = 1 } 
    actual = expected

let addExistingItemAssert = 
    let myOrder = { Id = 1; Items = [ { 
ProductId = 1; Quantity = 1 } ] }
    let expected = { Id = 1; Items = [ { 
ProductId = 1; Quantity = 2 } ] }
    let actual = myOrder |> addItem { 
ProductId = 1; Quantity = 1 } 
    actual = expected

We can easily add multiple items to an order:

let addItems items order = // Item list -> Order -> Order
    let items = 
        items @ order.Items 
        |> List.groupBy (fun i -> i.ProductId)
        |> List.map (fun (id, items) -> { ProductId = id; 
Quantity = items |> List.sumBy (fun i -> i.Quantity) })
        |> List.sortBy (fun i -> i.ProductId)
    { order with Items = items }

Add some asserts to the OrderTests.fsx file for the addItems function:

let addNewItemsAssert = 
    let myEmptyOrder = { Id = 1; Items = [] }
    let expected = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 1 }; { ProductId = 2; Quantity = 5 } ] }
    let actual = myEmptyOrder |> addItems [ { ProductId = 1; 
Quantity = 1 }; { ProductId = 2; Quantity = 5 } ]
    actual = expected

let addItemsAssert = 
    let myOrder = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let expected = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 2 }; { ProductId = 2; Quantity = 5 } ] }
    let actual = myOrder |> addItems [ { ProductId = 1; 
Quantity = 1 }; { ProductId = 2; Quantity = 5 } ]
    actual = expected

Let's extract the common functionality (group by and map) into a new function:

let recalculate items = // Item list -> Item list
    items
    |> List.groupBy (fun i -> i.ProductId)
    |> List.map (fun (id, items) -> { ProductId = id; 
Quantity = items |> List.sumBy (fun i -> i.Quantity) })

let addItem item order =
    let items = 
        item :: order.Items
        |> recalculate
    { order with Items = items }

let addItems items order =
    let items = 
        items @ order.Items 
        |> recalculate
        |> List.sortBy (fun i -> i.ProductId)
    { order with Items = items }

Run the changes into FSI and the verify using the asserts.

We could simplify/modify the addItem function to the following:

let addItem item order =
    { order with Items = item :: order.Items |> recalculate }

Removing an item can be easily achieved by filtering out the unwanted item by the productId:

let removeItem productId order =
    let items = 
        order.Items
        |> filter (fun x -> x.ProductId <> productId)
    { order with Items = items }

Again we write some asserts to verify our new function works as expected:

let removeExistingItemAssert = 
    let myEmptyOrder = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let expected = { Id = 1; Items = [] }
    let actual = myEmptyOrder |> removeItem 1 
    actual = expected

let removeNonexistantItemAssert = 
    let myOrder = { Id = 2; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let expected = { Id = 2; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let actual = myOrder |> removeItem 2 
    actual = expected

Reducing an item quantity is slightly more complex. Firstly we add an item with negative quantity, recalculate the items and then filter out any items with a quantity less than or equal to 0:

let reduceItem productId quantity order =
    let items = 
        { ProductId = productId; Quantity = -quantity } 
:: order.Items
        |> recalculate
        |> filter (fun x -> x.Quantity > 0)
    { order with Items = items }

Again we write some asserts to verify our new function works as expected:

let reduceSomeExistingItemAssert = 
    let myOrder = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 5 } ] }
    let expected = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 2 } ] }
    let actual = myEmptyOrder |> reduceItem 1 3
    actual = expected

let reduceAllExistingItemAssert = 
    let myOrder = { Id = 2; Items = [ { ProductId = 1; 
Quantity = 5 } ] }
    let expected = { Id = 2; Items = [] }
    let actual = myEmptyOrder |> reduceItem 1 5
    actual = expected

let reduceNonexistantItemAssert = 
    let myOrder = { Id = 3; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let expected = { Id = 3; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let actual = myOrder |> reduceItem 2 5
    actual = expected

let reduceNonexistantItemAssert = 
    let myEmptyOrder = { Id = 4; Items = [] }
    let expected = { Id = 4; Items = [] }
    let actual = myEmptyOrder |> reduceItem 2 5
    actual = expected

Clearing all of the items is really simple:

let clearItems order = 
    { order with Items = [] }

Write some asserts to verify our new function works as expected:

let clearItemsAssert = 
    let myOrder = { Id = 1; Items = [ { ProductId = 1; 
Quantity = 1 } ] }
    let expected = { Id = 1; Items = [] }
    let actual = myOrder |> clearItems
    actual = expected

let clearEmptyItemsAssert = 
    let myEmptyOrder = { Id = 2; Items = [] }
    let expected = { Id = 2; Items = [] }
    let actual = myEmptyOrder |> clearItems
    actual = expected

You should now convert all of the asserts we have written to real tests in OrderTests.fs in the test project.

For more details on the List module, have a look at the Language Reference in the F# Guide (https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/index).

Summary

In this post we have looked at some of the most useful functions on the List module and we have seen that it is possible to use immutable data structures to provide important business functionality. We are five posts into the series and we haven't mutated anything yet!

In the next post we will look at how to handle streams of data from a json source.

If you have any comments on this series of posts or suggestions for new ones, send me a tweet (@ijrussell) and let me know.

Part 4Table of ContentsPart 6

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 12

Explore reflection and meta-programming in F#. Learn how to dynamically manipulate code and enhance flexibility with advanced techniques.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 10

Discover Agents and Mailboxes in F#. Build responsive applications using these powerful concurrency tools in functional programming.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F#

Dive into functional programming with F# in our introductory series. Learn how to solve real business problems using F#'s functional programming features. This first part covers setting up your environment, basic F# syntax, and implementing a simple use case. Perfect for developers looking to enhance their skills in functional programming.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 9

Explore Active Patterns and Computation Expressions in F#. Enhance code clarity and functionality with these advanced techniques.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 7

Explore LINQ and query expressions in F#. Simplify data manipulation and enhance your functional programming skills with this guide.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 2

Explore functions, types, and modules in F#. Enhance your skills with practical examples and insights in this detailed guide.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 3

Dive into F# data structures and pattern matching. Simplify code and enhance functionality with these powerful features.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 8

Discover Units of Measure and Type Providers in F#. Enhance data management and type safety in your applications with these powerful tools.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 6

Learn error handling in F# with option types. Improve code reliability using F#'s powerful error-handling techniques.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 11

Learn type inference and generic functions in F#. Boost efficiency and flexibility in your code with these essential programming concepts.

Ian RusselIan RusselBlog
Blog

Introduction to Functional Programming in F# – Part 4

Unlock F# collections and pipelines. Manage data efficiently and streamline your functional programming workflow with these powerful tools.

Bernhard SchauerBlog
Blog

ADRs as a Tool to Build Empowered Teams

Learn how we use Architecture Decision Records (ADRs) to build empowered, autonomous teams, enhancing decision-making and collaboration.

Ian RusselIan RusselBlog
Blog

So, I wrote a book

Join me as I share the story of writing a book on F#. Discover the challenges, insights, and triumphs along the way.

Rinat AbdullinRinat AbdullinBlog
Blog

Process Pipelines

Discover how process pipelines break down complex tasks into manageable steps, optimizing workflows and improving efficiency using Kanban boards.

Christian FolieBlog
Blog

Running Hybrid Workshops

When modernizing or building systems, one major challenge is finding out what to build. In Pre-Covid times on-site workshops were a main source to get an idea about ‘the right thing’. But during Covid everybody got used to working remotely, so now the question can be raised: Is it still worth having on-site, physical workshops?

Rinat AbdullinRinat AbdullinBlog
Blog

Learning + Sharing at TIMETOACT GROUP Austria

Discover how we fosters continuous learning and sharing among employees, encouraging growth and collaboration through dedicated time for skill development.

Rinat AbdullinRinat AbdullinBlog
Blog

Innovation Incubator Round 1

Team experiments with new technologies and collaborative problem-solving: This was our first round of the Innovation Incubator.

Rinat AbdullinRinat AbdullinBlog
Blog

Innovation Incubator at TIMETOACT GROUP Austria

Discover how our Innovation Incubator empowers teams to innovate with collaborative, week-long experiments, driving company-wide creativity and progress.

Laura GaetanoBlog
Blog

5 lessons from running a (remote) design systems book club

Last year I gifted a design systems book I had been reading to a friend and she suggested starting a mini book club so that she’d have some accountability to finish reading the book. I took her up on the offer and so in late spring, our design systems book club was born. But how can you make the meetings fun and engaging even though you're physically separated? Here are a couple of things I learned from running my very first remote book club with my friend!

Laura GaetanoBlog
Blog

My Weekly Shutdown Routine

Discover my weekly shutdown routine to enhance productivity and start each week fresh. Learn effective techniques for reflection and organization.

Laura GaetanoBlog
Blog

Using a Skill/Will matrix for personal career development

Discover how a Skill/Will Matrix helps employees identify strengths and areas for growth, boosting personal and professional development.

Sebastian BelczykBlog
Blog

Building a micro frontend consuming a design system | Part 3

In this blopgpost, you will learn how to create a react application that consumes a design system.

Rinat AbdullinRinat AbdullinBlog
Blog

Consistency and Aggregates in Event Sourcing

Learn how we ensures data consistency in event sourcing with effective use of aggregates, enhancing system reliability and performance.

Rinat AbdullinRinat AbdullinBlog
Blog

Using NLP libraries for post-processing

Learn how to analyse sticky notes in miro from event stormings and how this analysis can be carried out with the help of the spaCy library.

Daniel PuchnerBlog
Blog

Make Your Value Stream Visible Through Structured Logging

Boost your value stream visibility with structured logging. Improve traceability and streamline processes in your software development lifecycle.

Daniel PuchnerBlog
Blog

How to gather data from Miro

Learn how to gather data from Miro boards with this step-by-step guide. Streamline your data collection for deeper insights.

Rinat AbdullinRinat AbdullinBlog
Blog

Event Sourcing with Apache Kafka

For a long time, there was a consensus that Kafka and Event Sourcing are not compatible with each other. So it might look like there is no way of working with Event Sourcing. But there is if certain requirements are met.

Christian FolieBlog
Blog

The Power of Event Sourcing

This is how we used Event Sourcing to maintain flexibility, handle changes, and ensure efficient error resolution in application development.

Peter SzarvasPeter SzarvasBlog
Blog

Why Was Our Project Successful: Coincidence or Blueprint?

“The project exceeded all expectations,” is one among our favourite samples of the very positive feedback from our client. Here's how we did it!

Sebastian BelczykBlog
Blog

Building A Shell Application for Micro Frontends | Part 4

We already have a design system, several micro frontends consuming this design system, and now we need a shell application that imports micro frontends and displays them.

Jonathan ChannonBlog
Blog

Tracing IO in .NET Core

Learn how we leverage OpenTelemetry for efficient tracing of IO operations in .NET Core applications, enhancing performance and monitoring.

Blog
Blog

My Workflows During the Quarantine

The current situation has deeply affected our daily lives. However, in retrospect, it had a surprisingly small impact on how we get work done at TIMETOACT GROUP Austria.

Sebastian BelczykBlog
Blog

Composite UI with Design System and Micro Frontends

Discover how to create scalable composite UIs using design systems and micro-frontends. Enhance consistency and agility in your development process.

Sebastian BelczykBlog
Blog

Building and Publishing Design Systems | Part 2

Learn how to build and publish design systems effectively. Discover best practices for creating reusable components and enhancing UI consistency.

Nina DemuthBlog
Blog

Trustbit ML Lab Welcomes Grayskull e150 by Tenstorrent

Discover how Trustbit ML Lab integrates Tenstorrent's Grayskull e150, led by Jim Keller, for cutting-edge, energy-efficient AI processing.

Aqeel AlazreeBlog
Blog

Part 2: Data Analysis with powerful Python

Analyzing and visualizing data from a SQLite database in Python can be a powerful way to gain insights and present your findings. In Part 2 of this blog series, we will walk you through the steps to retrieve data from a SQLite database file named gold.db and display it in the form of a chart using Python. We'll use some essential tools and libraries for this task.

Chrystal LantnikBlog
Blog

CSS :has() & Responsive Design

In my journey to tackle a responsive layout problem, I stumbled upon the remarkable benefits of the :has() pseudo-class. Initially, I attempted various other methods to resolve the issue, but ultimately, embracing the power of :has() proved to be the optimal solution. This blog explores my experience and highlights the advantages of utilizing the :has() pseudo-class in achieving flexible layouts.

Daniel WellerBlog
Blog

Revolutionizing the Logistics Industry

As the logistics industry becomes increasingly complex, businesses need innovative solutions to manage the challenges of supply chain management, trucking, and delivery. With competitors investing in cutting-edge research and development, it is vital for companies to stay ahead of the curve and embrace the latest technologies to remain competitive. That is why we introduce the TIMETOACT Logistics Simulator Framework, a revolutionary tool for creating a digital twin of your logistics operation.

Aqeel AlazreeBlog
Blog

Part 3: How to Analyze a Database File with GPT-3.5

In this blog, we'll explore the proper usage of data analysis with ChatGPT and how you can analyze and visualize data from a SQLite database to help you make the most of your data.

Christoph HasenzaglChristoph HasenzaglBlog
Blog

Common Mistakes in the Development of AI Assistants

How fortunate that people make mistakes: because we can learn from them and improve. We have closely observed how companies around the world have implemented AI assistants in recent months and have, unfortunately, often seen them fail. We would like to share with you how these failures occurred and what can be learned from them for future projects: So that AI assistants can be implemented more successfully in the future!

Rinat AbdullinRinat AbdullinBlog
Blog

So You are Building an AI Assistant?

So you are building an AI assistant for the business? This is a popular topic in the companies these days. Everybody seems to be doing that. While running AI Research in the last months, I have discovered that many companies in the USA and Europe are building some sort of AI assistant these days, mostly around enterprise workflow automation and knowledge bases. There are common patterns in how such projects work most of the time. So let me tell you a story...

Rinat AbdullinRinat AbdullinBlog
Blog

Let's build an Enterprise AI Assistant

In the previous blog post we have talked about basic principles of building AI assistants. Let’s take them for a spin with a product case that we’ve worked on: using AI to support enterprise sales pipelines.

Rinat AbdullinRinat AbdullinBlog
Blog

The Intersection of AI and Voice Manipulation

The advent of Artificial Intelligence (AI) in text-to-speech (TTS) technologies has revolutionized the way we interact with written content. Natural Readers, standing at the forefront of this innovation, offers a comprehensive suite of features designed to cater to a broad spectrum of needs, from personal leisure to educational support and commercial use. As we delve into the capabilities of Natural Readers, it's crucial to explore both the advantages it brings to the table and the ethical considerations surrounding voice manipulation in TTS technologies.

Christian FolieBlog
Blog

Designing and Running a Workshop series: An outline

Learn how to design and execute impactful workshops. Discover tips, strategies, and a step-by-step outline for a successful workshop series.

Rinat AbdullinRinat AbdullinBlog
Blog

Machine Learning Pipelines

In this first part, we explain the basics of machine learning pipelines and showcase what they could look like in simple form. Learn about the differences between software development and machine learning as well as which common problems you can tackle with them.

Daniel PuchnerBlog
Blog

How we discover and organise domains in an existing product

Software companies and consultants like to flex their Domain Driven Design (DDD) muscles by throwing around terms like Domain, Subdomain and Bounded Context. But what lies behind these buzzwords, and how these apply to customers' diverse environments and needs, are often not as clear. As it turns out it takes a collaborative effort between stakeholders and development team(s) over a longer period of time on a regular basis to get them right.

Felix KrauseBlog
Blog

Part 1: Detecting Truck Parking Lots on Satellite Images

Real-time truck tracking is crucial in logistics: to enable accurate planning and provide reliable estimation of delivery times, operators build detailed profiles of loading stations, providing expected durations of truck loading and unloading, as well as resting times. Yet, how to derive an exact truck status based on mere GPS signals?

Christian FolieBlog
Blog

Designing and Running a Workshop series: The board

In this part, we discuss the basic design of the Miro board, which will aid in conducting the workshops.

Rinat AbdullinRinat AbdullinBlog
Blog

LLM Performance Series: Batching

Beginning with the September Trustbit LLM Benchmarks, we are now giving particular focus to a range of enterprise workloads. These encompass the kinds of tasks associated with Large Language Models that are frequently encountered in the context of large-scale business digitalization.

Nina DemuthBlog
Blog

7 Positive effects of visualizing the interests of your team

Interests maps unleash hidden potentials and interests, but they also make it clear which topics are not of interest to your colleagues.

Felix KrauseBlog
Blog

Part 2: Detecting Truck Parking Lots on Satellite Images

In the previous blog post, we created an already pretty powerful image segmentation model in order to detect the shape of truck parking lots on satellite images. However, we will now try to run the code on new hardware and get even better as well as more robust results.

Rinat AbdullinRinat AbdullinBlog
Blog

State of Fast Feedback in Data Science Projects

DSML projects can be quite different from the software projects: a lot of R&D in a rapidly evolving landscape, working with data, distributions and probabilities instead of code. However, there is one thing in common: iterative development process matters a lot.

Felix KrauseBlog
Blog

License Plate Detection for Precise Car Distance Estimation

When it comes to advanced driver-assistance systems or self-driving cars, one needs to find a way of estimating the distance to other vehicles on the road.

Rinat AbdullinRinat AbdullinBlog
Blog

Trustbit LLM Leaderboard

To address common questions concerning the integration of Large Language Models, we have created an LLM Product Leaderboard that focuses on building and shipping products.

Felix KrauseBlog
Blog

Creating a Cross-Domain Capable ML Pipeline

As classifying images into categories is a ubiquitous task occurring in various domains, a need for a machine learning pipeline which can accommodate for new categories is easy to justify. In particular, common general requirements are to filter out low-quality (blurred, low contrast etc.) images, and to speed up the learning of new categories if image quality is sufficient. In this blog post we compare several image classification models from the transfer learning perspective.

Felix KrauseBlog
Blog

Boosting speed of scikit-learn regression algorithms

The purpose of this blog post is to investigate the performance and prediction speed behavior of popular regression algorithms, i.e. models that predict numerical values based on a set of input variables.

Rinat AbdullinRinat AbdullinBlog
Blog

Strategic Impact of Large Language Models

This blog discusses the rapid advancements in large language models, particularly highlighting the impact of OpenAI's GPT models.

Aqeel AlazreeBlog
Blog

Database Analysis Report

This report comprehensively analyzes the auto parts sales database. The primary focus is understanding sales trends, identifying high-performing products, Analyzing the most profitable products for the upcoming quarter, and evaluating inventory management efficiency.

Jörg EgretzbergerJörg EgretzbergerBlog
Blog

8 tips for developing AI assistants

AI assistants for businesses are hype, and many teams were already eagerly and enthusiastically working on their implementation. Unfortunately, however, we have seen that many teams we have observed in Europe and the US have failed at the task. Read about our 8 most valuable tips, so that you will succeed.

Aqeel AlazreeBlog
Blog

Part 1: Data Analysis with ChatGPT

In this new blog series we will give you an overview of how to analyze and visualize data, create code manually and how to make ChatGPT work effectively. Part 1 deals with the following: In the data-driven era, businesses and organizations are constantly seeking ways to extract meaningful insights from their data. One powerful tool that can facilitate this process is ChatGPT, a state-of-the-art natural language processing model developed by OpenAI. In Part 1 pf this blog, we'll explore the proper usage of data analysis with ChatGPT and how it can help you make the most of your data.

Matus ZilinskyBlog
Blog

Creating a Social Media Posts Generator Website with ChatGPT

Using the GPT-3-turbo and DALL-E models in Node.js to create a social post generator for a fictional product can be really helpful. The author uses ChatGPT to create an API that utilizes the openai library for Node.js., a Vue component with an input for the title and message of the post. This article provides step-by-step instructions for setting up the project and includes links to the code repository.

Rinat AbdullinRinat AbdullinBlog
Blog

5 Inconvenient Questions when hiring an AI company

This article discusses five questions you should ask when buying an AI. These questions are inconvenient for providers of AI products, but they are necessary to ensure that you are getting the best product for your needs. The article also discusses the importance of testing the AI system on your own data to see how it performs.

Aqeel AlazreeBlog
Blog

Part 4: Save Time and Analyze the Database File

ChatGPT-4 enables you to analyze database contents with just two simple steps (copy and paste), facilitating well-informed decision-making.

Rinat AbdullinRinat AbdullinBlog
Blog

Announcing Domain-Driven Design Exercises

Interested in Domain Dirven Design? Then this DDD exercise is perfect for you!

TIMETOACT
Service
Headerbild zu Application Modernization
Service

Application Modernization

Application Modernization focuses on modernizing existing applications. The key to success in Application Modernization is the strategy and selection of projects.

TIMETOACT
Technologie
Logo Atlassian Confluence
Technologie

Confluence from Atlassian

Create, organize, and collaborate on tasks - all in a single place. Confluence is a workspace for teams and organizations where you can store your documentation and collaboratively develop and share knowledge. Dynamic pages give your team a place to create, capture, and collaborate around projects or idea development.

TIMETOACT
News
News

TIMETOACT is Mendix training partner

We are convinced of Mendix's no-code/low-code platforms and are therefore not only a Mendix partner, but also a Mendix training partner.

Kompetenz
Kompetenz

AI - A technology is revolutionizing our everyday lives

For ARS, AI is an increasingly natural and organic part of software engineering. This is particularly true in cases where it is an integral part of applications and functions.

TIMETOACT
Technologie
Logo Jira Service Management
Technologie

Jira Service Management from Atlassian

Enable developers, operators, and other teams from different departments to collaborate and improve their service management responsiveness. Respond quickly to incidents, requests, and changes, and provide your customers with an optimized service experience.

Kompetenz
Kompetenz

DevOps and CI/CD

A DevOps introduction gains momentum and focus with the support of our experts. We record the initiatives and capture the context of the company.

Kompetenz
Kompetenz

ARS Golden 4

Agile development, DevOps, APIs and microservices are the state-of-the-art gold standards for their digital systems and products.

TIMETOACT
Service
Navigationsbilc zu Application Development
Service

Application Development

Application Development refers to the process of modifying, designing and/or developing one or more applications. Gaps in the software landscape can be closed by tailoring applications individually to the customer.

TIMETOACT
Service
Header zu Requirement Engineering
Service

Requirement Engineering

Requirement Engineering, also known as Requirements Analysis, is a central component of the Software Development process. In this process, the requirements for the system to be developed are defined using a systematic procedure.

TIMETOACT GROUP
Branche
Branche

Digital transformation in public administration

The digital transformation will massively change the world of work, especially in public administration. We support federal, state and local authorities in the strategic and technical implementation of their administrative modernisation projects.

TIMETOACT
Referenz
Referenz

Introduction of Jira to Hamburger Hochbahn

The Hamburger Hochbahn AG controls the development of its new mobility platform "Switchh" via the Atlassian project management tool Jira – introduced, administered and hosted by the TIMETOACT GROUP.

TIMETOACT
Technologie
Technologie

Advice around Mendix

Develop your solutions quickly and independently in low-code with the leading technology vendor. Use the Mendix toolkit and model your applications with visual elements.

TIMETOACT GROUP
Branche
Headerbild für lokale Entwicklerressourcen in Deutschland
Branche

On-site digitization partner for insurance companies

As TIMETOACT GROUP, we are one of the leading digitization partners for IT solutions in Germany, Austria and Switzerland. As your partner, we are there for you at 17 locations and will find the right solution on the path to digitization - gladly together in a personal exchange on site.

TIMETOACT
Technologie
Technologie

Our service offer for Mendix

The Dutch software manufacturer gives us the possibilities to create platform-independent low/no-code solutions for you with its products. In addition, we offer a wide range of services related to Mendix and are available to you from conceptual design to hosting and operation of your new solution.

TIMETOACT GROUP
Branche
Schild als Symbol für innere und äußere Sicherheit
Branche

Internal and external security

Defense forces and police must protect citizens and the state from ever new threats. Modern IT & software solutions support them in this task.

Kompetenz
Kompetenz

Software Engineering

Software engineering is the art of creating good software. Software engineering is the discipline of creating your digital products using methods proven by science and practice.

TIMETOACT
Referenz
Referenz

Interactive online portal identifies suitable employees

TIMETOACT digitizes several test procedures for KI.TEST to determine professional intelligence and personality.

Service
Service

Cloud Transformation & Container Technologies

Public, private or hybrid? We can help you develop your cloud strategy so you can take full advantage of the technology.

TIMETOACT
Service
Header zu Fullstack Development
Service

Fullstack Development

The trend in Software Development is towards Full-Stack Development. Full-stack developers are programmers who work in both frontend and backend development and thus have competencies in the areas of databases, servers, systems and clients.

TIMETOACT GROUP
Service
Headerbild zur offenen und sicheren IT bei Versicherungen
Service

Open and secure IT

Just a few years ago, insurers were reluctant to move into the cloud or platform world. Concerns about security and governance often prevailed. The paradigm has changed. Insurers are looking at cloud solutions and are increasingly willing to rely on standard solutions for core applications as well.

TIMETOACT
Technologie
Atlassian Logo
Technologie

Bamboo, Bitbucket, Sourcetree

Continuous Integration and a Continuous Delivery Pipeline with Bamboo, Bitbucket and Sourcetree. We can help you with our years of experience as a user as well as a solution partner of Atlassian products in many areas.

Service
Service

Application Integration & Process Automation

Digitizing and improving business processes and responding agilely to change – more and more companies are facing these kind of challenges. This makes it all the more important to take new business opportunities through integrated and optimized processes based on intelligent, digitally networked systems.

TIMETOACT
Referenz
Referenz

The digital customer file with IBM Content Manager

The prefabricated house specialist SchwörerHaus KG has relied on IBM technology for many years to set up a digital customer file.

TIMETOACT GROUP
News
News

Proof-of-Value Workshop

Today's businesses need data integration solutions that offer open, reusable standards and a complete, innovative portfolio of data capabilities. Apply for one of our free workshops!

IPG
Marco RohrerMarco RohrerBlog
Hintergrundgrafik für IPG Partner Clearsky
Blog

Bring IT service management and IAM systems together

How do companies bring their complex IT service management and IAM systems together in an end user-friendly way? In our interview, Clear Skye and the IPG Group show, how it works very easily

TIMETOACT
Technologie
Headerbild zu Containerisierung mit Open Source
Technologie

Containerisation with Open Source

Containerization is the next stage of virtualization and provides secure and easy compartmentalization of individual applications. The process of deploying an app has been simplified many times in recent years.

Service
Service

Managed Service: Mailroom

In the TIMETOACT mailroom, business documents are converted into data in a highly efficient manner and returned securely to the end customer for further processing.

TIMETOACT
News
News

HCL license and price adjustments as of 8.8.2024

HCL Software has informed us that the license and maintenance prices for the various product categories will be increased as of 8.8.2024.

TIMETOACT
Technologie
Headerbild zu Incident Kommunikation Management
Technologie

Incident communication management

Statuspage allows you to keep track of the status of individual system-relevant components as well as a history of past incidents. Our self-created solution also allows you to connect various monitoring tools and query them in specific cycles. The component failure automatically generates an e-mail to your ticket system.

TIMETOACT
Blog
Blog

TIMETOACT starts with the implementation of ESG-Suit

Compliance with ESG and sustainability standards is mandatory for companies in order to meet the requirements of the EU's Corporate Sustainability Reporting Directive (CSRD).

Service
Service

Software, Mobile and Web App Development

Standard software often cannot completely fulfill a company's own requirements - TIMETOACT therefore develops customized software solutions.