Whereas Elixir is a functional programming language, it’s varied from loads of the more than a few standard functional languages fancy Haskell, Scala, OCaml, and F#.

Elixir pragmatically handles concurrent programs with high fault tolerance. In varied phrases, Elixir is an FP language on legend of this naturally suits it, and no longer for its dangle sake. So, porting idioms blindly from Haskell to Elixir can lead to undesired outcomes.

### Featured Content Ads

add advertising hereAt the identical time, Elixir users must nonetheless more continually consult with the complete pleasant universe of functors, monads, and varied curiosities. Good-looking out libraries were presented for working with algebraic structures.

On this article, I want to introduce you to a library known as Witchcraft and conceal tips on how to utilize it to emulate Haskell-model programming in Elixir.

## String Validation and Processing with Witchcraft

We are in a position to plow via a bank card validation exercise.

Given a string that must safe a bank card number, we want to make certain that that:

### Featured Content Ads

add advertising here- it comprises 16 digits
- it has at least two varied digits
- the final digit is even
- the sum of the digits is better than 16

We are in a position to carry out this exercise with `Both`

, undoubtedly one of the predefined info kinds that the Witchcraft complex presents.

### Region Up Witchcraft

First, add the mandatory libraries to your `mix.exs`

file and speed `mix deps.glean`

.

```
{: witchcraft, git: "https://github.com/doma-engineering/witchcraft.git", ref: "9c31c75"},
{: algae, git: "https://github.com/doma-engineering/algae.git", ref: "e9b8f88"},
{: quark, git: "https://github.com/witchcrafters/quark.git", ref: "b05a8a0"},
```

### Parsing the String

First, form a recent module and import Witchcraft at the cease of the module.

```
defmodule Card carry out
use Witchcraft
discontinue
```

Then, write a fair to parse the string accurate into a listing of digits and score away all non-digit gadgets.

### Featured Content Ads

add advertising here```
def get_digits(cardnumber) carry out
cardnumber
|> String.spoil up("", properly-organized: correct)
|> Enum.scheme(fn x -> Integer.parse(x) discontinue)
|> Enum.filter(fn x -> x != : error discontinue)
|> Enum.scheme(fn {int, _rest} -> int discontinue
discontinue
```

In the code above, we spoil up the card number into characters and scheme `Integer.parse`

(profitable integer conversion) over them. `Integer.parse`

returns both `{int, rest_of_binary}`

or `:error`

. We filter out the errors and unpack the tuples with the final two capabilities.

```
iex(1)> Card.get_digits("3456-3233-5689-4445")
[3, 4, 5, 6, 3, 2, 3, 3, 5, 6, 8, 9, 4, 4, 4, 5]
```

After that, we can write our first validation fair with `Both`

.

### Rapid Intro to the `Both`

Knowledge Form

`Both`

is a form that comprises undoubtedly one of two varied choices: `Left`

or `Upright`

. Every of these wraps one other kind. `Left`

retail outlets failures, and `Upright`

retail outlets successes.

```
-- Both info kind as outlined in Haskell
info Both a b = Left a | Upright b
```

Generally, we return it from computations that would perchance perchance fail whenever you happen to pray to know what more or much less error made them fail.

When working with Witchcraft, you presumably can use the predefined Algae.Both to create recent cases of the `Both`

info kind. We are in a position to carry out that by the use of undoubtedly one of two structs: `%Algae.Both.Left{left: model}`

or `%Algae.Both.Upright{staunch: model}`

.

Seemingly, you salvage already speed into it someplace. In varied languages, it’s most regularly known as `Result`

(in Rust, shall we embrace). It’s also structurally identical to the tuple continually archaic in Elixir.

```
{: okay, end result} -> {: staunch, end result} -> %Algae.Both.Upright{staunch: end result}
{: error, motive} -> {: left, motive} -> %Algae.Both.Left{left: motive}
```

In actuality, we would perchance perchance well technically use the tuple for our exercise. I’ve constructed it this contrivance on motive, so that you presumably can bump into the equipment of Witchcraft while staying on roughly right floor.

### Instance of `Both`

Let’s see at an example of `Both`

.

We salvage parsed a listing of digits from the given string, and now we want to know whether or no longer there are 16 gadgets in the checklist. If we took the easy contrivance out, we would perchance perchance well write one thing fancy this:

`def sixteen_digits(cardnumber), carry out: Enum.depend(cardnumber) == 16`

Unfortunately, the fair above is no longer very composable: the return model loses the card number, so we won’t be ready to pipe the to carry out additional computations on it.

Which capacity of this truth, we need the to be a more complex constructing similar to `Both`

.

- If there are 16 digits in the checklist, we want to return an
`Both.Upright`

with the checklist. - If there would possibly well be a certain series of digits, we want to return an
`Both.Left`

with`:not_16_digits`

.

And here’s the fair to carry out that:

```
def sixteen_digits(cardnumber) carry out
case Enum.depend(cardnumber) carry out
16 -> %Algae.Both.Upright{staunch: cardnumber}
_ -> %Algae.Both.Left{left: : not_16_digits}
discontinue
discontinue
```

Let’s strive it out in `iex`

:

```
iex(1)> right_number = Card.get_digits("3456-3233---5689-4445")
[3, 4, 5, 6, 3, 2, 3, 3, 5, 6, 8, 9, 4, 4, 4, 5]
iex(2)> Card.sixteen_digits(right_number)
%Algae.Both.Upright{staunch: [3, 4, 5, 6, 3, 2, 3, 3, 5, 6, 8, 9, 4, 4, 4, 5]}
iex(3)> wrong_number = Card.get_digits("444")
[4, 4, 4]
iex(4)> Card.sixteen_digits(wrong_number)
%Algae.Both.Left{left: :not_16_digits}
```

### Other Validation Features

In the identical contrivance, we can form a validation rule for every requirement.

I counsel you are attempting doing it your self first since they are going to be the same to the first example.

To remind you, here are the stipulations we want to ascertain:

- The number has at least two varied digits.
- The closing digit of the number is even.
- The sum of the digits is better than 16.

Every of the stipulations would possibly want to salvage its dangle fair. Every of the capabilities must nonetheless score a listing of numbers and return:

`%Algae.Both.Upright{}`

with the checklist inside of if the condition is fulfilled`%Algae.Both.Left{}`

with the motive inside of if the condition is no longer fulfilled

Whereas you’re ready to proceed, here are the capabilities that I’ll use additional on listed here:

```
def two_unique_digits(cardnumber) carry out
ordinary =
cardnumber
|> Enum.uniq()
|> Enum.depend()
case ordinary >= 2 carry out
correct -> %Algae.Both.Upright{staunch: cardnumber}
_ -> %Algae.Both.Left{left: : not_2_unique_digits}
discontinue
discontinue
def final_even(cardnumber) carry out
last_digit = Enum.at(cardnumber, -1)
case rem(last_digit, 2) carry out
0 -> %Algae.Both.Upright{staunch: cardnumber}
_ -> %Algae.Both.Left{left: : last_not_even}
discontinue
discontinue
def sum_greater_than_16(cardnumber) carry out
case Enum.sum(cardnumber) >= 16 carry out
correct -> %Algae.Both.Upright{staunch: cardnumber}
_ -> %Algae.Both.Left{left: : sum_smallr_than_16}
discontinue
discontinue
```

### Connecting the Features

However how carry out we be half of these capabilities together? Every of them takes a listing but returns a struct. We are in a position to’t pipe them into every varied on legend of their kinds don’t match up.

To chain them, we need one thing that knows tips on how to unwrap `Algae.Both`

and apply varied capabilities to what’s inside of, and Witchcraft has lawful the ingredient we need.

```
definst Witchcraft.Chain, for: Algae.Both.Left carry out
def chain(left, _), carry out: left
discontinue
definst Witchcraft.Chain, for: Algae.Both.Upright carry out
def chain(%Upright{staunch: info}, link), carry out: link.(info)
discontinue
```

*From Algae.Both.*

`chain`

, which is ready to even be written in Witchcraft as `>>>`

(or `bind`

), is the precious bind operator from Haskell: `>>=`

. Let’s impress what it does.

As outlined for `Both`

, this can score a model — both `Left `

or `Upright`

— and a fair from a conventional model to `Both`

.

In the case of `Left`

, this can ignore the fair and pass the model additional. In the case of `Upright`

, this can apply the fair to the model inside of `Upright`

.

In our code, we can conveniently use `>>>`

so that it looks pipe-y.

```
def parse_number(cardnumber) carry out
cardnumber
|> get_digits()
|> sixteen_digits()
>>> fn x -> two_unique_digits(x) discontinue
>>> fn x -> final_even(x) discontinue
>>> fn x -> sum_greater_than_16(x) discontinue
discontinue
```

Unfortunately, the opt syntax (`&two_unique_digits/1`

) doesn’t work here. (The macro will magnify the code to nested captures, which Elixir doesn’t enable you carry out via `&`

.)

Combining the `Both`

info kind and its outlined chain fair lets us construct up a chain of capabilities. Even supposing they score a listing and return an `Both`

, the capabilities would perchance perchance well furthermore be chained to come at a end result. The complete chain will return the checklist in case of success and the first encountered error in the case of failure.

We are in a position to strive it out in `iex`

.

```
iex(1)> Card.parse_number("4444-444-222-1")
%Algae.Both.Left{left: :not_16_digits}
iex(2)> Card.parse_number("4444-4444-4444-4444")
%Algae.Both.Left{left: :not_2_unique_digits}
iex(3)> Card.parse_number("4444-4444-4444-4435")
%Algae.Both.Left{left: :last_not_even}
iex(4)> Card.parse_number("1020-0000-0000-0000")
%Algae.Both.Left{left: :sum_smaller_than_16}
iex(5)> Card.parse_number("4545-3232-5423-6788")
%Algae.Both.Upright{staunch: [4, 5, 4, 5, 3, 2, 3, 2, 5, 4, 2, 3, 6, 7, 8, 8]}
```

From this point onward, you presumably can content to salvage written monadic code in Elixir.

### Tinkering With the Codebase

Listed below are some minor changes we can form to the code so it looks nicer. These are no longer wanted to your working out but can present you more practice with the code example in request.

First off, Witchcraft presents a extraordinarily at hand `~>`

operator that does the identical as piping into `Enum.scheme`

.

We are in a position to use it in our `get_digits`

fair.

```
def get_digits(cardnumber) carry out
cardnumber
|> String.spoil up("", properly-organized: correct)
~> fn x -> Integer.parse(x) discontinue
|> Enum.filter(fn x -> x != : error discontinue)
~> fn {int, _rest} -> int discontinue
discontinue
```

After that, empty lists will trigger some speed-time errors with the `Enum.at`

that we archaic, and having empty inputs doubtlessly isn’t half of the plan, so we can reject empty strings staunch at the originate.

```
def get_digits(cardnumber) carry out
digits =
cardnumber
|> String.spoil up("", properly-organized: correct)
~> fn x -> Integer.parse(x) discontinue
|> Enum.filter(fn x -> x != : error discontinue)
~> fn {int, _rest} -> int discontinue
case digits carry out
[] -> %Algae.Both.Left{left: : empty_input}
_ -> %Algae.Both.Upright{staunch: digits}
discontinue
discontinue
```

And at final, there would possibly well be a macro that you presumably can use in `parse_number`

to simulate a more Haskell-fancy contrivance of writing a series of actions in a definite context. This model is most regularly known as the carry out-notation.

```
def parse_number(cardnumber) carry out
monad %Algae.Both.Upright{} carry out
digits <- get_digits(cardnumber)
a <- sixteen_digits(digits)
b <- two_unique_digits(a)
c <- final_even(b)
d <- sum_greater_than_16(c)
return(d)
end
end
```

In the code sample above, we provide the kind of container that we will operate with — `%Algae.Either.Right{}`

. Then we can do actions inside it, and the `monad`

macro will automatically chain our functions. In the end, it will return whatever we put in the return statement (but wrapped in the container).

It’s very powerful, but also very confusing at first. If it is hard to understand what’s happening here, I encourage you to try out `monad []`

first since it is very similar to list comprehensions. In fact, if you think of this macro as generalized list comprehensions, you won’t err too much.

`Either`

and the Result Tuple in Elixir

`Either`

is very similar to the result tuple in Elixir, and I’ve done that on purpose to keep you on somewhat familiar ground.

In fact, you can implement the same thing without using Witchcraft.

```
defmodule Card2 do
def get_digits(cardnumber) do
digits =
cardnumber
|> String.spoil up("", properly-organized: correct)
|> Enum.scheme(fn x -> Integer.parse(x) discontinue)
|> Enum.filter(fn x -> x != : error discontinue)
|> Enum.scheme(fn {int, _rest} -> int discontinue)
discontinue
def sixteen_digits(cardnumber) carry out
case Enum.depend(cardnumber) carry out
16 -> {: okay, cardnumber}
_ -> {: error, : not_16_digits}
discontinue
discontinue
def two_unique_digits(cardnumber) carry out
ordinary =
cardnumber
|> Enum.uniq()
|> Enum.depend()
case un
```

NOW WITH OVER +8500 USERS. __ other folks can Be a half of Knowasiak for free. Register on Knowasiak.com__

Read More