raw version of blog posts

master
Mahdi Dibaiee 2022-07-27 09:48:57 +01:00
parent ae0fc73214
commit 908f0c65d5
30 changed files with 1812 additions and 763 deletions

View File

@ -1,3 +0,0 @@
mahdi.blog
==========

View File

@ -19,31 +19,6 @@ collections:
art:
title: art
permalink: /art/:path/
#math:
#title: math
#output: true
#permalink: /math/:path/
#path: /math
#programming:
#title: programming
#output: true
#permalink: /programming/:path/
#path: /programming
#life:
#title: life
#output: true
#permalink: /life/:path/
#path: /life
#travel:
#title: travel
#output: true
#permalink: /travel/:path/
#path: /travel
#philosophy:
#title: philosophy
#output: true
#permalink: /philosophy/:path/
#path: /philosophy
contentsLabel: "Table of Contents"
showToggleButton: true

View File

@ -1,7 +0,0 @@
<div class="share-page">
Share in
<a href="https://twitter.com/intent/tweet?text={{ page.title }}&url={{ site.url }}{{ page.url }}&via={{ site.twitter_username }}&related={{ site.twitter_username }}" rel="nofollow" target="_blank" title="Share on Twitter">Twitter</a>
<a href="https://facebook.com/sharer.php?u={{ site.url }}{{ page.url }}" rel="nofollow" target="_blank" title="Share on Facebook">Facebook</a>
<a href="https://plus.google.com/share?url={{ site.url }}{{ page.url }}" rel="nofollow" target="_blank" title="Share on Google+">Google+</a>
</div>

View File

@ -12,6 +12,7 @@ layout: default
<span>{{ page.date | date: "%b %-d, %Y" }}</span>
{% if page.meta %} • <span>{{ page.meta }}</span>{% endif %}
<span>Reading time: {{ content | reading_time }}</span>
<span><a href="/raw{{ page.url }}">raw</a></span>
</p>
</div>
@ -19,8 +20,6 @@ layout: default
{{ content }}
</article>
{% include share.html %}
<div id="commento"></div>
<script defer
src="//commento.mahdi.blog/js/commento.js">

5
_layouts/raw.html Normal file
View File

@ -0,0 +1,5 @@
<pre>
# {{ page.title }}
{{ page.content }}
</pre>

30
_plugins/raw.rb Normal file
View File

@ -0,0 +1,30 @@
module RawGenerator
class Generator < Jekyll::Generator
priority :lowest
def generate(site)
existing_posts = site.posts.docs.to_a
for i in 0..(existing_posts.size - 1) do
post = existing_posts[i]
new_page = RawPage.new(site, post)
site.pages << new_page
end
end
end
class RawPage < Jekyll::Page
def initialize(site, post)
@site = site # the current site instance.
@base = site.source # path to the source directory.
@dir = "raw" # the directory the page will reside in.
@name = post.name # basically @basename + @ext.
@content = post.content
@data = post.data.clone
@relative_path = post.relative_path.sub("_posts", "raw")
data["permalink"] = 'raw/%{permalink}' % {permalink: post.permalink}
@ext = '.md'
data["layout"] = 'raw'
end
end
end

View File

@ -7,20 +7,32 @@ categories: programming
author: Mahdi
---
I've been working on the [CSS Filter Editor widget](https://bugzilla.mozilla.org/show_bug.cgi?id=1055181) in Firefox Developer Tools for a couple of weeks, thanks to [Patrick Brosset](https://medium.com/@patrickbrosset) for mentoring me and [Tim Nguyen](https://github.com/nt1m) for his great contributions.
I've been working on the [CSS Filter Editor
widget](https://bugzilla.mozilla.org/show_bug.cgi?id=1055181) in Firefox
Developer Tools for a couple of weeks, thanks to [Patrick
Brosset](https://medium.com/@patrickbrosset) for mentoring me and [Tim
Nguyen](https://github.com/nt1m) for his great contributions.
Here is an [online version](http://mdibaiee.github.io/CSS-Filter-Tooltip/) to use as a playground. This version is modified to be cross-browser and therefore is a little different from the original widget used in Firefox.
Here is an [online version](http://mdibaiee.github.io/CSS-Filter-Tooltip/) to
use as a playground. This version is modified to be cross-browser and therefore
is a little different from the original widget used in Firefox.
You can also use [David Walsh's demo](http://davidwalsh.name/demo/css-filters.php), although it doesn't have as much flexibility.
You can also use [David Walsh's
demo](http://davidwalsh.name/demo/css-filters.php), although it doesn't have as
much flexibility.
CSS Filters are supported by most modern browsers ([Can I Use CSS Filters](http://caniuse.com/#feat=css-filters)), if your browser doesn't support this, please change your browser (I recommend [Firefox](https://www.mozilla.org/en-US/firefox/new/)).
I don't like long-bla-bla-articles, so let's get to it.
CSS Filters are supported by most modern browsers ([Can I Use CSS
Filters](http://caniuse.com/#feat=css-filters)), if your browser doesn't
support this, please change your browser (I recommend
[Firefox](https://www.mozilla.org/en-US/firefox/new/)).
Introduction
============
CSS Filters introduce a few useful effects and some image adjusting functions, namely blur, drop-shadow, contrast, brightness, [and a few others](https://developer.mozilla.org/en-US/docs/Web/CSS/filter) which can be really useful if used properly.
CSS Filters introduce a few useful effects and some image adjusting functions,
namely blur, drop-shadow, contrast, brightness, [and a few
others](https://developer.mozilla.org/en-US/docs/Web/CSS/filter) which can be
really useful if used properly.
A simple demo showing blur, contrast and brightness combined (hover over image):
@ -34,9 +46,11 @@ Length
Percentage
----------
These filters accept percentage values, but if you omit the percentage sign, the value is multiplied by 100, e.g. `contrast(2)` is another way of writing `contrast(200%)`. Negative values have the same effect as zero.
These filters accept percentage values, but if you omit the percentage sign,
the value is multiplied by 100, e.g. `contrast(2)` is another way of writing
`contrast(200%)`. Negative values have the same effect as zero.
Most filters explain themselves, I'm not going to repeat \`Adjusts ${x} level\` like a parrot.
Most filters explain themselves:
* brightness
* contrast
@ -48,19 +62,28 @@ Percentage
### invert
I first understood how cool this filter can be after I saw Tim Nguyen using this in theme switching. Yeah you can't invert everything and "Yay, I have a new theme", but you can use invert on some elements and it works flawlessly, believe me.
I first understood how cool this filter can be after I saw Tim Nguyen using
this in theme switching. Yeah you can't invert everything and "Yay, I have a
new theme", but you can use invert on some elements and it works flawlessly,
believe me.
<iframe width="100%" height="100" src="//jsfiddle.net/mdibaiee/373dnby8/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### opacity
You might wonder why do we have this function, as we already have an opacity property in CSS, that's because the opacity property is not hardware accelerated, but the filter property is hardware accelerated in most browsers, which includes this function.
You might wonder why do we have this function, as we already have an opacity
property in CSS, that's because the opacity property is not hardware
accelerated, but the filter property is hardware accelerated in most
browsers, which includes this function.
Angle
-----
hue-rotate is the only function to accept an angle value (degree / radian).
###hue-rotate
If you're familiar with [Hue](https://en.wikipedia.org/wiki/Hue) you probably know that it's measured by angles. The hue-rotate rotates the hue circle of an image relative to it's current hue value (360 and 0 have the same results).
If you're familiar with [Hue](https://en.wikipedia.org/wiki/Hue) you probably
know that it's measured by angles. The hue-rotate rotates the hue circle of
an image relative to it's current hue value (360 and 0 have the same
results).
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/smk922fh/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
@ -69,13 +92,20 @@ Special
These filter's don't fit in any of the groups above, they have special/mixed values.
### drop-shadow
The drop-shadow filter accepts a *shadow-list*, four length values, and one color. box-shadow and text-shadow also accept shadow lists.
The drop-shadow filter accepts a *shadow-list*, four length values, and one
color. box-shadow and text-shadow also accept shadow lists.
You're probably familiar with shadow lists already: `drop-shadow(x y radius spread color)`. Unfortunaly spread doesn't work in either Chrome or Firefox as of this writing — It is treated as an error.
You're probably familiar with shadow lists already: `drop-shadow(x y radius spread color)`.
Unfortunaly spread doesn't work in either Chrome or Firefox as of this writing — It is treated as an error.
drop-shadow is pretty cool, as it doensn't have the limitations of box-shadow and text-shadow. box-shadow applies a shadow to the outer shape, but drop-shadow applies a shadow to elements independant to their shape, they might be triangles, PNG's with transparent background or just anything.
drop-shadow is pretty cool, as it doensn't have the limitations of box-shadow
and text-shadow. box-shadow applies a shadow to the outer shape, but
drop-shadow applies a shadow to elements independant to their shape, they
might be triangles, PNG's with transparent background or just anything.
drop-shadow clones the element's image, moves it to the offset defined, applies blur and changes it's color, putting it under the original element. Couldn't do it better:
drop-shadow clones the element's image, moves it to the offset defined,
applies blur and changes it's color, putting it under the original element.
Couldn't do it better:
![drop-shadow explained](/img/dropshadow.gif)
@ -84,7 +114,9 @@ Special
<iframe width="100%" height="150" src="//jsfiddle.net/mdibaiee/z077vbs0/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
### url
With the url function we have the power of CSS and SVG Filters in one place. You can reference an SVG element by linking to it with a hash of the filter element's ID:
With the url function we have the power of CSS and SVG Filters in one place.
You can reference an SVG element by linking to it with a hash of the filter
element's ID:
{% highlight css %}
filter: url(/example.svg#filter)
@ -99,7 +131,9 @@ filter: url(/example.svg#filter)
{% include caption.html text='Source: http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html' %}
Custom Filters allows usage of vertex and fragment shaders which run directly in the GPU. Custom filters' specs is subject to change, so there's no implementation yet. For more info on this topic follow the links below:
Custom Filters allows usage of vertex and fragment shaders which run directly
in the GPU. Custom filters' specs is subject to change, so there's no
implementation yet. For more info on this topic follow the links below:
* [Getting started with CSS custom filters](http://alteredqualia.com/css-shaders/article/#shaders)
* [Introducing CSS shaders: Cinematic effects for the web](http://www.adobe.com/devnet/archive/html5/articles/css-shaders.html)
@ -108,7 +142,8 @@ filter: url(/example.svg#filter)
Gotchas
=======
You now have a basic understanding of filters, good. Here are a few gotchas you'd better know.
You now have a basic understanding of filters, good. Here are a few gotchas
you'd better know.
Order matters
-------------
@ -118,13 +153,15 @@ The order in which filters are applied matters. Take this example:
filter: blur(10px) contrast(2);
{% endhighlight %}
Hey, browser, please blur the element, then double the contrast of the blurred element. (blurred parts have their contrast affected)
Hey, browser, please blur the element, then double the contrast of the blurred
element. (blurred parts have their contrast affected)
{% highlight css %}
filter: contrast(2) blur(10px);
{% endhighlight %}
Hey browser, please double the contrast of my element, then blur it out. (high contrast image is blurred normally)
Hey browser, please double the contrast of my element, then blur it out. (high
contrast image is blurred normally)
Here is the actual comparison:
@ -133,14 +170,22 @@ Here is the actual comparison:
Inheritance
-----------
Okay, you now know the order of filters matters, the filter property is not actually *inherited*, but when you apply a filter on a parent element, of course it's children are affected too, but what if the children have their own css filters? Ah-ha! CSS properties are applied bottom-up, which means childrens' filters are applied first.
Okay, you now know the order of filters matters, the filter property is not
actually *inherited*, but when you apply a filter on a parent element, of
course it's children are affected too, but what if the children have their own
css filters? Ah-ha! CSS properties are applied bottom-up, which means
childrens' filters are applied first.
<iframe width="100%" height="300" src="//jsfiddle.net/mdibaiee/o40d7cs7/embedded/result,css" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
Implementation
--------------
I said using the url function we have "the power of CSS and SVG filters in one place", but the CSS filters are actually implemented using SVG filters! You know, the functions are actually referencing to an svg generated in the browser. Here is the list of [CSS Filter equivalents](http://www.w3.org/TR/filter-effects/#ShorthandEquivalents).
I said using the url function we have "the power of CSS and SVG filters in one
place", but the CSS filters are actually implemented using SVG filters! You
know, the functions are actually referencing to an svg generated in the
browser. Here is the list of [CSS Filter
equivalents](http://www.w3.org/TR/filter-effects/#ShorthandEquivalents).
Go Wild
=======

View File

@ -12,9 +12,12 @@ is a new API used to communicate between same-origin tabs opened by the same use
Why
===
Let's say you open two GitHub tabs, the [rust repository](https://github.com/rust-lang/rust) and [your stars](https://github.com/stars) page. You decide to star the awesome rust repository, but then you have to
refresh your stars page to see your new star. That's sad. There must be a way for GitHub to refresh
your stars page in case you star something in another tab, right?
Let's say you open two GitHub tabs, the [rust
repository](https://github.com/rust-lang/rust) and [your
stars](https://github.com/stars) page. You decide to star the awesome rust
repository, but then you have to refresh your stars page to see your new star.
That's sad. There must be a way for GitHub to refresh your stars page in case
you star something in another tab, right?
![Broadcast Channels, SATISFIED](/img/broadcast-channels.jpg)
@ -48,11 +51,14 @@ BroadcastChannels are pretty easy, here I'm going over the small details.
Creating channels
-----------------
BroadcastChannels are constructed with a single argument, their name. Browsing contexts should use
this name to communicate over a specified channel. There's no limit to how many channels you can create.
BroadcastChannels are constructed with a single argument, their name. Browsing
contexts should use this name to communicate over a specified channel. There's
no limit to how many channels you can create.
In the first sentence of article I said it's used to communicate between tabs, but it's actually "browsing contexts".
[Browsing contexts](http://www.w3.org/TR/html5/browsers.html#browsing-context) are any environments owning a `Document`, e.g. tabs, windows, iframes, etc.
In the first sentence of article I said it's used to communicate between tabs,
but it's actually "browsing contexts". [Browsing
contexts](http://www.w3.org/TR/html5/browsers.html#browsing-context) are any
environments owning a `Document`, e.g. tabs, windows, iframes, etc.
{% highlight javascript %}
var channel = new BroadcastChannel('star');
@ -79,7 +85,9 @@ Channels inherit from [`EventTarget`](https://developer.mozilla.org/en-US/docs/W
Channels have only one event:
### message
The event object passed to this event is a [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) with the `data` property set to the actual message sent using `postMessage`.
The event object passed to this event is a
[`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
with the `data` property set to the actual message sent using `postMessage`.
---
@ -88,7 +96,9 @@ Another example
Let's Fix GitHub
----------------
Okay, let's try something cool, I promise you will love it. Open a browser with [BroadcastChannel support](http://caniuse.com/#feat=broadcastchannel) and Install [GreaseMonkey](http://www.greasespot.net/).
Okay, let's try something cool, I promise you will love it. Open a browser with
[BroadcastChannel support](http://caniuse.com/#feat=broadcastchannel) and
Install [GreaseMonkey](http://www.greasespot.net/).
You have to add two scripts, one for repository pages, and one for the stars page.
@ -134,4 +144,5 @@ is open, and your stars page will refresh immediately.
That's it, I really like this API as it's best of both worlds, simple and useful.
There are a lot of things which can be done with help of BroadcastChannels, I would love to hear your feedback on this API.
There are a lot of things which can be done with help of BroadcastChannels, I
would love to hear your feedback on this API.

View File

@ -7,16 +7,25 @@ categories: programming
author: Mahdi
---
Array comprehension is a new feature proposed for ES7, with a new syntax
to create new arrays from existing [iterables](http://www.2ality.com/2015/02/es6-iteration.html),
comprehensions can replace map and filter.
Array comprehension is a new feature proposed for ES7, with a new syntax to
create new arrays from existing
[iterables](http://www.2ality.com/2015/02/es6-iteration.html), comprehensions
can replace map and filter.
Generator comprehension brings the same feature to generators, this is a more
useful feature as it removes the need to write new generators for simple map/filter operations.
useful feature as it removes the need to write new generators for simple
map/filter operations.
Generator comprehensions allow us to easily write single-line generators, which can replace our arrays in some situations, you might ask why we might consider replacing arrays with generators, the most important reason is their [laziness](#laziness). I've explained laziness later in the article.
Generator comprehensions allow us to easily write single-line generators, which
can replace our arrays in some situations, you might ask why we might consider
replacing arrays with generators, the most important reason is their
[laziness](#laziness). I've explained laziness later in the article.
Comprehensions are currently only supported by Firefox, use Firefox 30+ or [Babel](https://babeljs.io/repl/) to run the examples. The Node.js version of examples using generator `function* ()`s is available at the [repository](https://github.com/mdibaiee/array-vs-generator) (doesn't require transpilation, use latest node).
Comprehensions are currently only supported by Firefox, use Firefox 30+ or
[Babel](https://babeljs.io/repl/) to run the examples. The Node.js version of
examples using generator `function* ()`s is available at the
[repository](https://github.com/mdibaiee/array-vs-generator) (doesn't require
transpilation, use latest node).
Syntax
======
@ -83,12 +92,15 @@ console.table(Array.from(nested));
Laziness
========
This is one of the most important advantages of generators over arrays and things alike.
The reason why I'm including this here is to give you a good reason to write generators instead of arrays
while generator comprehensions make it extremely easy to write them — this is a proof of their usefulness.
This is one of the most important advantages of generators over arrays and
things alike. The reason why I'm including this here is to give you a good
reason to write generators instead of arrays while generator comprehensions make
it extremely easy to write them — this is a proof of their usefulness.
In programming, laziness means doing nothing until the results are requested or in simpler terms, avoiding unnecessary work.
For example, when you create an array and map it, the result will be evaluated no matter you need it now or not, you need the whole thing or a part of it, etc.
In programming, laziness means doing nothing until the results are requested or
in simpler terms, avoiding unnecessary work. For example, when you create an
array and map it, the result will be evaluated no matter you need it now or not,
you need the whole thing or a part of it, etc.
Take this example:
@ -102,11 +114,14 @@ let first = bigArray.map(n => n * n)[0];
console.log(first);
{% endhighlight %}
You know what happens here, first, map is evaluated, returning thousands of squared numbers, then
the first element is returned. We must allocate and evaluate the whole squared array to be able to know about it's first or second element.
You know what happens here, first, map is evaluated, returning thousands of
squared numbers, then the first element is returned. We must allocate and
evaluate the whole squared array to be able to know about it's first or second
element.
Think of optimizing it, is it possible to get the desired result without storing
temporary arrays in memory? Can we get the first number directly without consuming a big chunk of memory?
temporary arrays in memory? Can we get the first number directly without
consuming a big chunk of memory?
Yes, using generators, Look at this:
@ -122,11 +137,17 @@ let squared = ( for (n of bigGenerator()) n * n );
console.log(squared.next());
{% endhighlight %}
Let's see what happens in this case.
Here, we create a generator which will yield numbers 0...100000, nothing is actually allocated or evaluated, we just have a generator which will return a new number every time we call `next()`.
Then we use generator comprehension to create another generator which squares the numbers our `bigGenerator()` yields, again, we don't evaluate or allocate anything, we just create a generator which will call another generator's `next()` method, square the results, and yield it.
Let's see what happens in this case. Here, we create a generator which will
yield numbers 0...100000, nothing is actually allocated or evaluated, we just
have a generator which will return a new number every time we call `next()`.
Then we use generator comprehension to create another generator which squares
the numbers our `bigGenerator()` yields, again, we don't evaluate or allocate
anything, we just create a generator which will call another generator's
`next()` method, square the results, and yield it.
Now when we call `squared.next()`, the `squared` generator calls `bigArray().next()`, squares the results and yields it, it doesn't do any unnecessary work, it's lazy.
Now when we call `squared.next()`, the `squared` generator calls
`bigArray().next()`, squares the results and yields it, it doesn't do any
unnecessary work, it's lazy.
[
![Generator diagram](/img/generator-diagram.png)

View File

@ -7,7 +7,8 @@ categories: programming
author: Mahdi
---
In this article, I'm going over creating an autocompletion/prediction system using a data-structure called Trie, it's fast and easy to customize.
In this article, I'm going over creating an autocompletion/prediction system
using a data-structure called Trie, it's fast and easy to customize.
Trie
====
@ -76,20 +77,27 @@ class Trie {
}
}
{% endhighlight %}
Every Trie must have a root node with empty value, that's how our single-character nodes follow the rule of Tries.
Every Trie must have a root node with empty value, that's how our
single-character nodes follow the rule of Tries.
Ok, our first method, `add` handles adding a value to the trie, creating necessary parent nodes for our value.
At each iteration, we compare the `i`th character of our value, with `i`th character of current node's children's value,
if we find one, we continue to search the next branch, else, we create a node with `value.slice(0, i + 1)` and move onto the created node.
Ok, our first method, `add` handles adding a value to the trie, creating
necessary parent nodes for our value. At each iteration, we compare the `i`th
character of our value, with `i`th character of current node's children's value,
if we find one, we continue to search the next branch, else, we create a node
with `value.slice(0, i + 1)` and move onto the created node.
It might be a little hard to grasp at first, so I created a visualization of this method to help you understand it easier, take a look:
It might be a little hard to grasp at first, so I created a visualization of
this method to help you understand it easier, take a look:
[Trie Visualization](https://mdibaiee.github.io/autocomplete-trie/demo/add.html)
Then we have our find method, which searches for the given value in the trie. The algorithm for searching is the same, comparing by index and moving to the next branch.
Then we have our find method, which searches for the given value in the trie.
The algorithm for searching is the same, comparing by index and moving to the
next branch.
Example
========
That's it for our simple Trie class, now let's create an actual input with autocomplete functionality using our Trie.
# Example
That's it for our simple Trie class, now let's create an actual input with
autocomplete functionality using our Trie.
{% highlight html %}
<input>
@ -137,12 +145,15 @@ input.addEventListener('keyup', () => {
{% endhighlight %}
[Autocomplete 1](https://mdibaiee.github.io/autocomplete-trie/1.html)
![Autocomplete 1](/img/autocomplete-1.png)
This will only show the instant-childs of the word entered, but that's not what we want, we want to show *complete* words, how do we do that?
This will only show the instant-childs of the word entered, but that's not what
we want, we want to show *complete* words, how do we do that?
First, we need a way to detect complete words, we can have a flag to recognize complete words, we can modify our `add` method to
automatically flag whole words or we can manually add the flag after adding the node, as we did by setting a category for our words,
so we already have a flag to recognize whole words, that's our `category` property, now let's add a new method to our Trie class to find
whole words.
First, we need a way to detect complete words, we can have a flag to recognize
complete words, we can modify our `add` method to automatically flag whole words
or we can manually add the flag after adding the node, as we did by setting a
category for our words, so we already have a flag to recognize whole words,
that's our `category` property, now let's add a new method to our Trie class to
find whole words.
{% highlight javascript %}
...
@ -205,4 +216,6 @@ That's it! We have an input with autocomplete and tab-to-next-char. Isn't it awe
[Final Result](https://mdibaiee.github.io/autocomplete-trie/2.html)
*Pst! I have a repository of algorithm implementations in ES6, you might want to take a look! [mdibaiee/harmony-algorithms](https://github.com/mdibaiee/harmony-algorithms)*
*Pst! I have a repository of algorithm implementations in ES6, you might want to
take a look!
[mdibaiee/harmony-algorithms](https://github.com/mdibaiee/harmony-algorithms)*

View File

@ -7,44 +7,58 @@ categories: programming
author: Mahdi
---
I have been doing Open-source for a while, I don't call myself an "expert" or something like that,
but I'd like to share my opinion and experience on contributing to, and maintaining open-source code.
I have been doing Open-source for a while, I don't call myself an "expert" or
something like that, but I'd like to share my opinion and experience on
contributing to, and maintaining open-source code.
So, I've been following and contributing to open-source projects for quite a time,
and I have had different experiences every time. There are always good and bad experiences
along a road, it's never a heaven, never a hell. I've had contributions as small as fixing a typo in README, and as big
as adding a new feature to Firefox Developer Tools or refactoring a whole repository!
So, I've been following and contributing to open-source projects for quite a
time, and I have had different experiences every time. There are always good and
bad experiences along a road, it's never a heaven, never a hell. I've had
contributions as small as fixing a typo in README, and as big as adding a new
feature to Firefox Developer Tools or refactoring a whole repository!
Here I'm going to share my experiences and what I've learned along the way that you should consider
if you want to take this road.
Here I'm going to share my experiences and what I've learned along the way that
you should consider if you want to take this road.
The Good
--------
I love open-source, it's awesome how people share their efforts with others, and others give feedback to
the maintainer to make the software better. It's an always-growing system, even if a maintainer stops maintaining,
it's possible to _fork_ a repository and continue it, although not as easy, but possible.
# The Good I love open-source, it's awesome how people share their efforts with
others, and others give feedback to the maintainer to make the software better.
It's an always-growing system, even if a maintainer stops maintaining, it's
possible to _fork_ a repository and continue it, although not as easy, but
possible.
The best part of doing open-source, in my opinion, is building connections and learning from others.
The best part of doing open-source, in my opinion, is building connections and
learning from others.
Whether you are maintaining or contributing to a project, you are going to learn new things, it just happens.
Whether you are maintaining or contributing to a project, you are going to learn
new things, it just happens.
If you are a maintainer of a repository with a countable amount of users, you are going to constantly learn your mistakes from others,
finding these mistakes by yourself is really hard, because you can't easily look at a subject _the other way_,
but users have this potential to look at your code with their eyes, seeing mistakes you can't see.
If you are a maintainer of a repository with a countable amount of users, you
are going to constantly learn your mistakes from others, finding these mistakes
by yourself is really hard, because you can't easily look at a subject _the
other way_, but users have this potential to look at your code with their eyes,
seeing mistakes you can't see.
If you are contributing, following or just exploring projects, you are definitely going to learn, the solutions people suggest to a problem,
the way they communicate, etc.
Usually, not always, the maintainer has a better knowledge over the subject of project than you, so you are going to learn from him and other contributors
by reading their code or exploring the issues and how they've been solved. I personally learned a lot this way. I would volunteer to fix a bug, then the maintainer and other contributors would show up to give their suggestions and ideas on the issue, which I would then learn from. I also subscribe to interesting issues that I don't know how to fix to see how they get solved.
If you are contributing, following or just exploring projects, you are
definitely going to learn, the solutions people suggest to a problem, the way
they communicate, etc. Usually, not always, the maintainer has a better
knowledge over the subject of project than you, so you are going to learn from
him and other contributors by reading their code or exploring the issues and how
they've been solved. I personally learned a lot this way. I would volunteer to
fix a bug, then the maintainer and other contributors would show up to give
their suggestions and ideas on the issue, which I would then learn from. I also
subscribe to interesting issues that I don't know how to fix to see how they get
solved.
The Bad
-------
First off, the most annoying thing about open-source contributions is that people (I'm looking at you, maintainers) think
that contributors are jobless bored people who don't know how to spend their time and have come to waste some time on some random open-source project, NO, seriously.
# The Bad First off, the most annoying thing about open-source contributions is
that people (I'm looking at you, maintainers) think that contributors are
jobless bored people who don't know how to spend their time and have come to
waste some time on some random open-source project, NO, seriously.
I have a job, I totally care about my time and I'm not making a Pull-request because I'm bored.
I have a job, I totally care about my time and I'm not making a Pull-request
because I'm bored.
Now, why is that important to know: it has happened to me a couple of times that I ask on an issue:
Now, why is that important to know: it has happened to me a couple of times that
I ask on an issue:
_"- Okay, I'm interested, what **exactly** has to be done?"_
@ -54,34 +68,49 @@ _... some time later_
_"- Here is x, y and z, please review and merge"
_"- Oh, thank you very much, but you know, now that I think of it, I don't want x, y or even z. Closing."
_"- Oh, thank you very much, but you know, now that I think of it, I don't want
x, y or even z. Closing."
and I'm like:
<!-- ![Are you kidding me?](/img/are-you-kidding-me.jpg) -->
<img alt='Are you kidding me?' src='/img/are-you-kidding-me.jpg' />
<!-- ![Are you kidding me?](/img/are-you-kidding-me.jpg) --> <img alt='Are you
kidding me?' src='/img/are-you-kidding-me.jpg' />
{% include caption.html text='Are you kidding me?' %}
This is the worst thing that can happen to you, try to avoid it, you don't want your valuable time wasted.
This is the worst thing that can happen to you, try to avoid it, you don't want
your valuable time wasted.
How to avoid it you ask, there is a sign that I've found which leads to this problem most of the time and that's **lack of clear specification**, just like with clients, if the maintainer doesn't specify what should be done, you should stop.
How to avoid it you ask, there is a sign that I've found which leads to this
problem most of the time and that's **lack of clear specification**, just like
with clients, if the maintainer doesn't specify what should be done, you should
stop.
It happened to me, just like the past discussion, except he didn't tell me _"Please do x, y, z"_, he made himself look
too busy and said: _"The title says it all"_, no, it doesn't say it all. "x, y and z" can be implemented in `2^9` ways, and sadly,
you are not going to accept the `192`th way, as you "don't like it". Do not get trapped in these time-wasting situations, I wish maintainers understood how valuable people's times are.
It happened to me, just like the past discussion, except he didn't tell me
_"Please do x, y, z"_, he made himself look too busy and said: _"The title says
it all"_, no, it doesn't say it all. "x, y and z" can be implemented in `2^9`
ways, and sadly, you are not going to accept the `192`th way, as you "don't like
it". Do not get trapped in these time-wasting situations, I wish maintainers
understood how valuable people's times are.
The Ugly
--------
The sad part about open-source is, if the maintainer decides not to support the project anymore,
people will _kind of_ suffer. If the maintainer abandons the project, the project is *almost* doomed, as forking and continuing is really hard, reading the code from bottom up and understanding it isn't easy, and as there is no outcome, people usually decide to abandon a project once they lose interest in the topic.
# The Ugly The sad part about open-source is, if the maintainer decides not to
support the project anymore, people will _kind of_ suffer. If the maintainer
abandons the project, the project is *almost* doomed, as forking and continuing
is really hard, reading the code from bottom up and understanding it isn't easy,
and as there is no outcome, people usually decide to abandon a project once they
lose interest in the topic.
If I personally lose interest in a project I've made, I'll abandon it, I will try to guide new users through but I usually
don't offer as much support, I have more important things to do, it's really sad, but true.
If I personally lose interest in a project I've made, I'll abandon it, I will
try to guide new users through but I usually don't offer as much support, I have
more important things to do, it's really sad, but true.
To prevent this from happening, you must be able to make money out of your project, or your project must be really interesting
and challenging to keep you working on it.
To prevent this from happening, you must be able to make money out of your
project, or your project must be really interesting and challenging to keep you
working on it.
------
That's it, please note that everything you read here is my opinion, it's not a rule, not a judgment, it's my opinion and experience. If you would like to discuss this further, put a comment below or reach me at [twitter](https://twitter.com/mdibaiee).
That's it, please note that everything you read here is my opinion, it's not a
rule, not a judgment, it's my opinion and experience. If you would like to
discuss this further, put a comment below or reach me at
[twitter](https://twitter.com/mdibaiee).

View File

@ -7,67 +7,78 @@ excerpt_separator: <!--more-->
author: Mahdi
---
We are all going to die, we all know that well.<br /><br />
Now I want to take you to a world of immortals where humans don't die,
they live and live and live and... you know, live. From now on, pretend I'm a human
on this world of immortals, I'm immortal bitches.
We are all going to die, we all know that well.<br /><br /> Now I want to take
you to a world of immortals where humans don't die, they live and live and live
and... you know, live. From now on, pretend I'm a human on this world of
immortals, I'm immortal bitches.
![immortals chatting](/img/immortals.jpg)
{% include caption.html text='There is no campfire because they don\'t need it' %}
![immortals chatting](/img/immortals.jpg) {% include caption.html text='There is
no campfire because they don\'t need it' %}
<!--more-->
---
<!--more--> ---
In this world, there is no excitement in jumping from a cliff or doing flips over walls
or pretending to be a bird or even loving each other, in general, there is no
excitement in any experience, because there is nothing to miss if I don't do that right now,
I will always have another chance to do that again, even if that's going to be a thousand years from now,
because you know, we're all good at waiting here.
In this world, there is no excitement in jumping from a cliff or doing flips
over walls or pretending to be a bird or even loving each other, in general,
there is no excitement in any experience, because there is nothing to miss if I
don't do that right now, I will always have another chance to do that again,
even if that's going to be a thousand years from now, because you know, we're
all good at waiting here.
There is no technology and no fast transportation system here,
because, hell, who gives a fuck about fast transportation systems.
There is no technology and no fast transportation system here, because, hell,
who gives a fuck about fast transportation systems.
Who gives a shit about tools to harvest more food, or something you can write with,
you can know about our meaningless past as much as you want, there are always people to tell you about that.
Who gives a shit about tools to harvest more food, or something you can write
with, you can know about our meaningless past as much as you want, there are
always people to tell you about that.
Who cares if 2 + 2 = 4 or 5, I'm not going to die if the non-existing plane crashes because of an error,
none of that is needed.
Who cares if 2 + 2 = 4 or 5, I'm not going to die if the non-existing plane
crashes because of an error, none of that is needed.
We have an infinite amount of time to explore the globe, but we don't,
because there is no fun in doing that, how is that, you might ask. Someone from your world told me
I should explain it this way:
We have an infinite amount of time to explore the globe, but we don't, because
there is no fun in doing that, how is that, you might ask. Someone from your
world told me I should explain it this way:
> Simple mathematics we know says, in an infinite timespan, no other timespan is significant, basically,
any number divided by infinity yields zero. Your neighbour could tell you about how he spent a thousand years
exploring Earth, eating bugs and trying different methods to kill himself, and you could tell him
he literally spent 0% of his life doing all that, same as you, who just stood there.
>
> ![any fucking number / infinity = 0](/img/division-by-infinity.jpg)
> Simple mathematics we know says, in an infinite timespan, no other timespan is
significant, basically, any number divided by infinity yields zero. Your
neighbour could tell you about how he spent a thousand years exploring Earth,
eating bugs and trying different methods to kill himself, and you could tell him
he literally spent 0% of his life doing all that, same as you, who just stood
there. > > ![any fucking number / infinity = 0](/img/division-by-infinity.jpg)
Now I don't understand much of that, but I had enough time, and nothing else to do, to repeat this to myself
since he told me that until now.
Now I don't understand much of that, but I had enough time, and nothing else to
do, to repeat this to myself since he told me that until now.
Here, in this world, we can't suicide, if that was an option, we know well that we would go extinct
soon after finding out the fact that we are immortals, we really don't like this numb life.
Here, in this world, we can't suicide, if that was an option, we know well that
we would go extinct soon after finding out the fact that we are immortals, we
really don't like this numb life.
---
_Pooof_
Alright I'm back. You see, we need death, we really do, without death our lives
would be meaningless, we would have no purpose. Okay we would probably still [contribute to increase of entropy of the universe](https://www.youtube.com/watch?v=HxTnqKuNygE), but that's not what we _want_ to be here for, we want a higher purpose in life, and it's death that gifts us this
higher purpose.
would be meaningless, we would have no purpose. Okay we would probably still
[contribute to increase of entropy of the
universe](https://www.youtube.com/watch?v=HxTnqKuNygE), but that's not what we
_want_ to be here for, we want a higher purpose in life, and it's death that
gifts us this higher purpose.
When I was a kid, I was told that in order to stay alive after death, you have to submit your name on this planet, and
in this universe if possible. I know, that might sound ridiculous, but aren't we all fighting for the same thing, but in our own
ways? Maybe you just want to be remembered between a specific group of people (and that's perfectly fine) or you might
actually want to become a global role model, like Gandhi, Albert Einstein and people alike, it doesn't matter, what matters is,
we all want to be remembered for what we've done in our way to the end.
When I was a kid, I was told that in order to stay alive after death, you have
to submit your name on this planet, and in this universe if possible. I know,
that might sound ridiculous, but aren't we all fighting for the same thing, but
in our own ways? Maybe you just want to be remembered between a specific group
of people (and that's perfectly fine) or you might actually want to become a
global role model, like Gandhi, Albert Einstein and people alike, it doesn't
matter, what matters is, we all want to be remembered for what we've done in our
way to the end.
Immortals go extinct, but mortals find a mission to accomplish before the
deadline. Be grateful for this gift of death.
<!--It's not all about being famous, it's about being role model for a lot of people, there are lots of famous people and celebrities-->
<!--that will be forgotten after a decade or two, but some people are remembered forever, either for doing very good or very bad to others,-->
<!--I don't think Albert Einstein, Gandhi and Hitler will be forgotten in the near future (near as in thousand years).-->
<!--They are global role models, we want to be like some of them and avoid being like others (okay, maybe not absolutely global, but you get it).-->
<!--It's not all about being famous, it's about being role model for a lot of
people, there are lots of famous people and celebrities--> <!--that will be
forgotten after a decade or two, but some people are remembered forever, either
for doing very good or very bad to others,--> <!--I don't think Albert Einstein,
Gandhi and Hitler will be forgotten in the near future (near as in thousand
years).--> <!--They are global role models, we want to be like some of them and
avoid being like others (okay, maybe not absolutely global, but you get it).-->

View File

@ -9,64 +9,88 @@ author: Mahdi
**High-Frequency Fuck-Ups**:
> The cyclic process of "pushing yourself hard for a week, getting something done, and then feeling depressed and fucked up
for the next week"
> The cyclic process of "pushing yourself hard for a week, getting something
done, and then feeling depressed and fucked up for the next week"
Sounds familiar? Read on.
![High-Frequency Fuck-ups](/img/productivity-chart.jpg)
{% include caption.html text='Visual demonstration of High-Frequency Fuck-ups' %}
![High-Frequency Fuck-ups](/img/productivity-chart.jpg) {% include caption.html
text='Visual demonstration of High-Frequency Fuck-ups' %}
<!--more-->
Basically, you push yourself so fucking hard that you become a superstar in a week, and then all of a sudden
you are under a rain of hopelessness. All depression triggers start clicking and you are
lost. At best, you spend a week of depression and start rising to productivity again, but that's it,
it's a cycle you never exit and it gets worse and worse with every iteration, your depressions become longer
and longer unless you understand you don't need to climb a slope of 89° to become a superstar,
you can do it on a 45°, or even 20°, or even 1°, only it takes patience, but works out much better!
Basically, you push yourself so fucking hard that you become a superstar in a
week, and then all of a sudden you are under a rain of hopelessness. All
depression triggers start clicking and you are lost. At best, you spend a week
of depression and start rising to productivity again, but that's it, it's a
cycle you never exit and it gets worse and worse with every iteration, your
depressions become longer and longer unless you understand you don't need to
climb a slope of 89° to become a superstar, you can do it on a 45°, or even 20°,
or even 1°, only it takes patience, but works out much better!
I used to be on High-Frequency Fuck-ups for almost a year, after entering college and getting a job at the same time,
I was under a lot of pressure, I wanted to be best in my work, and in my college, and in everything! Okay, that's not
bad on it's own, but I was on the wrong road, I thought that's the way it has to work, you push yourself for some time,
get 5% of the road down, and then you get depressed, but you just have to go through it. But I was wrong, badly wrong.
I used to be on High-Frequency Fuck-ups for almost a year, after entering
college and getting a job at the same time, I was under a lot of pressure, I
wanted to be best in my work, and in my college, and in everything! Okay, that's
not bad on it's own, but I was on the wrong road, I thought that's the way it
has to work, you push yourself for some time, get 5% of the road down, and then
you get depressed, but you just have to go through it. But I was wrong, badly
wrong.
I only got more and more frustrated with my life, I started hating my job, hating my college and everything in between.
My depressions used to be a few days at max after each iteration of superstar-ism at first, but it got worse until I reached depressions
of two weeks. I couldn't attend to my exercise anymore, I wouldn't read the books I wanted to, even my social life was
breaking apart, I was dead, I only knew how to work some stuff out in short spans of time, but I couldn't control the
side effect it brought, the depression.
I only got more and more frustrated with my life, I started hating my job,
hating my college and everything in between. My depressions used to be a few
days at max after each iteration of superstar-ism at first, but it got worse
until I reached depressions of two weeks. I couldn't attend to my exercise
anymore, I wouldn't read the books I wanted to, even my social life was breaking
apart, I was dead, I only knew how to work some stuff out in short spans of
time, but I couldn't control the side effect it brought, the depression.
To be honest, those superstar peaks felt really good as I would actually accomplish things I couldn't do before, in a just week!
That's why I kept this habit for a year, but at some point I realised this is not going to work long-term, with the rate of
depressions getting longer and longer, I was risking _my life_, who knows what would've happened once I got to a whole month,
or even two months of depression, and I couldn't be saved, I was in a state of denial, I thought
"These people don't understand! That's the path you have to take to be great!", so I wouldn't listen to anyone telling me to slow the fuck down.
To be honest, those superstar peaks felt really good as I would actually
accomplish things I couldn't do before, in a just week! That's why I kept this
habit for a year, but at some point I realised this is not going to work
long-term, with the rate of depressions getting longer and longer, I was risking
_my life_, who knows what would've happened once I got to a whole month, or even
two months of depression, and I couldn't be saved, I was in a state of denial, I
thought "These people don't understand! That's the path you have to take to be
great!", so I wouldn't listen to anyone telling me to slow the fuck down.
At the time, I had two roommates, and they knew about my state, it was so visible, I would work like robots for a week, bumped up
and excited, and then I would go down for the next week, feeling groggy and sad the whole time.
At the time, I had two roommates, and they knew about my state, it was so
visible, I would work like robots for a week, bumped up and excited, and then I
would go down for the next week, feeling groggy and sad the whole time.
One night I and one of my roommates, Saeed, started talking, not directly about this topic, but we got there and he told me
I should slow down and move at a more controllable pace. He was not the only one telling me that, I was told this a lot,
either directly or indirectly, but I always denied it. This time, I thought about it, a lot, because I was tired of my High-Frequency Fuck-ups,
yet I was not sure if he was right or I was, so I continued my High-Frequency Fuck-ups for another two or three months
before deciding I should at least _try_ slowing down.
One night I and one of my roommates, Saeed, started talking, not directly about
this topic, but we got there and he told me I should slow down and move at a
more controllable pace. He was not the only one telling me that, I was told this
a lot, either directly or indirectly, but I always denied it. This time, I
thought about it, a lot, because I was tired of my High-Frequency Fuck-ups, yet
I was not sure if he was right or I was, so I continued my High-Frequency
Fuck-ups for another two or three months before deciding I should at least _try_
slowing down.
I slowly slowed down, the depressions went away, I would accomplish the things I wanted, only slightly longer, but damn, it was great!
I could continue getting stuff done without feeling fucked up and crying whole days and nights in my bed, I could do the things I loved
without any fucking side effects!
I slowly slowed down, the depressions went away, I would accomplish the things I
wanted, only slightly longer, but damn, it was great! I could continue getting
stuff done without feeling fucked up and crying whole days and nights in my bed,
I could do the things I loved without any fucking side effects!
At first, I had the doubt "Am I becoming one of _those_ people? People who don't get things done and don't grow?", but after some time,
I realised I am actually getting things done much better! It was easy to see for me and the people around me that I was much happier,
I was in control of my life and I was enjoying it. The only difference was patience, instead of rushing to get the next big thing done
in a short amount of time, I took patience in checking my list off, and suddenly everything was much more fun.
At first, I had the doubt "Am I becoming one of _those_ people? People who don't
get things done and don't grow?", but after some time, I realised I am actually
getting things done much better! It was easy to see for me and the people around
me that I was much happier, I was in control of my life and I was enjoying it.
The only difference was patience, instead of rushing to get the next big thing
done in a short amount of time, I took patience in checking my list off, and
suddenly everything was much more fun.
Now I study, play an instrument, exercise everyday, go running, read books, watch movies, write, eat and sleep well all at the same time,
and I don't feel a bit depressed. Sadness is something, depression is another, I do get sad, but not depressed. I feel alive and active.
Now I study, play an instrument, exercise everyday, go running, read books,
watch movies, write, eat and sleep well all at the same time, and I don't feel a
bit depressed. Sadness is something, depression is another, I do get sad, but
not depressed. I feel alive and active.
I've become much better socially, my interactions with my friends are much more alive now. I could see it in my friends' eyes when I used to
be a robot, they were like "What the fuck is going on with you man?", yes, exactly that phrase, but now I'm no longer a slave of High-Frequency Fuck-ups,
I have so much fun with my friends.
I've become much better socially, my interactions with my friends are much more
alive now. I could see it in my friends' eyes when I used to be a robot, they
were like "What the fuck is going on with you man?", yes, exactly that phrase,
but now I'm no longer a slave of High-Frequency Fuck-ups, I have so much fun
with my friends.
The takeaway is, stop High-Frequency Fuck-ups, slow down, take things one bite at a time and you will eventually accomplish what you are aiming for,
if only with a little more patience, you won't have depression blocking your way and fogging your brain every other week.
The takeaway is, stop High-Frequency Fuck-ups, slow down, take things one bite
at a time and you will eventually accomplish what you are aiming for, if only
with a little more patience, you won't have depression blocking your way and
fogging your brain every other week.

View File

@ -7,20 +7,23 @@ excerpt_separator: <!--more-->
author: Mahdi
---
When it comes to relationships, most (unsuccessful) people are _chasing_ the good ones.
They spend time trying to find their dream partner, the perfect match, but hey, do you qualify
as the dream partner of your dream partner? You fantasize about your dream partner, but have you ever
thought what kind of partner does he/she dream of?
When it comes to relationships, most (unsuccessful) people are _chasing_ the
good ones. They spend time trying to find their dream partner, the perfect
match, but hey, do you qualify as the dream partner of your dream partner? You
fantasize about your dream partner, but have you ever thought what kind of
partner does he/she dream of?
![I want an angel with...](/img/angel.jpg)
{% include caption.html text='I want an angel with...' %}
![I want an angel with...](/img/angel.jpg) {% include caption.html text='I want
an angel with...' %}
<!--more-->
It seems to be pretty acceptable in the society to start _looking_ for a _good_ partner once you
reach a certain age (depending on the country), and that's when people start defining for themselves what
a _good_ partner means. What do they want out of a relationship? Well, most beginners just want sex, that's one thing,
but I'm talking about real, intimate relationships. The definition usually goes like this:
It seems to be pretty acceptable in the society to start _looking_ for a _good_
partner once you reach a certain age (depending on the country), and that's when
people start defining for themselves what a _good_ partner means. What do they
want out of a relationship? Well, most beginners just want sex, that's one
thing, but I'm talking about real, intimate relationships. The definition
usually goes like this:
I want him/her to have
* Money
@ -29,28 +32,45 @@ I want him/her to have
* Empathy
* ...
Alright fine, that's a good and necessary step while thinking about a relationship.
Alright fine, that's a good and necessary step while thinking about a
relationship.
Now there are two groups of people after this step, let's call them Group A and Group B.
Now there are two groups of people after this step, let's call them Group A and
Group B.
Group A's next step is to start looking for partners, which usually follows by installing Tinder, OkCupid and a bunch of other
dating apps, spending more time in the bar, etc. Well it makes sense to start looking for a partner at first glance, but people in Group A
are missing an important point here, they defined what a _good partner_ means in their dictionary of life, but they haven't
really looked into their _good partner_'s dictionary to see what he/she wants out of a relationship, because if you don't qualify her requirements,
it's not a deal.
Group A's next step is to start looking for partners, which usually follows by
installing Tinder, OkCupid and a bunch of other dating apps, spending more time
in the bar, etc. Well it makes sense to start looking for a partner at first
glance, but people in Group A are missing an important point here, they defined
what a _good partner_ means in their dictionary of life, but they haven't really
looked into their _good partner_'s dictionary to see what he/she wants out of a
relationship, because if you don't qualify her requirements, it's not a deal.
Now there is a sub-group of Group A, too, and it includes the people who faced with the question "am I what she dreams of?", they
try to cheat and modify their definition of a good partner, adding a line that goes "Loves me however I am", sorry buddy, but what if I
tell you she could add the same line to her dictionary? That's not a deal, you want a good partner as you defined it, you have to be a good partner
as she defines it.
Now there is a sub-group of Group A, too, and it includes the people who faced
with the question "am I what she dreams of?", they try to cheat and modify their
definition of a good partner, adding a line that goes "Loves me however I am",
sorry buddy, but what if I tell you she could add the same line to her
dictionary? That's not a deal, you want a good partner as you defined it, you
have to be a good partner as she defines it.
On the other hand, Group B doesn't follow the same path as Group A. Group B starts by trying to predict what his dream partner would want
out of a relationship. Empathy? Loyalty? Knowledge? Body? They take a pen and a paper out and write a list of what they think their dream partner
would want them to have, what would she want them to be, and they start working on those, and I bet it's not going to be easy, knowledge doesn't pop up
after a good night's sleep, you have to spend years reading books and learning to get it. A good body doesn't _poof_ out if you wish it to, you have
to spend years being committed to exercise and eating well, and that's not easy. After all, what you define as a good partner ain't easy either, is it?
On the other hand, Group B doesn't follow the same path as Group A. Group B
starts by trying to predict what his dream partner would want out of a
relationship. Empathy? Loyalty? Knowledge? Body? They take a pen and a paper out
and write a list of what they think their dream partner would want them to have,
what would she want them to be, and they start working on those, and I bet it's
not going to be easy, knowledge doesn't pop up after a good night's sleep, you
have to spend years reading books and learning to get it. A good body doesn't
_poof_ out if you wish it to, you have to spend years being committed to
exercise and eating well, and that's not easy. After all, what you define as a
good partner ain't easy either, is it?
Now do you want your dream partner to fall for you the way you fall for her, without having to chase her with a net? Write down a list of
qualifications you expect your dream partner to look for, and start working your ass off reaching them, and I tell you, you will have a much easier _next step_ after this. You won't have to chase girls hoping the 34th one doesn't reject you because "she likes you however you are".
Now do you want your dream partner to fall for you the way you fall for her,
without having to chase her with a net? Write down a list of qualifications you
expect your dream partner to look for, and start working your ass off reaching
them, and I tell you, you will have a much easier _next step_ after this. You
won't have to chase girls hoping the 34th one doesn't reject you because "she
likes you however you are".
If I know one thing about life, it's the fact that you have to work your ass off in order to reach your dreams, dreams aren't easy, and a deep, intimate relationship really is a dream.
If I know one thing about life, it's the fact that you have to work your ass off
in order to reach your dreams, dreams aren't easy, and a deep, intimate
relationship really is a dream.

View File

@ -12,9 +12,14 @@ author: Mahdi
![general view of the forest](/img/primitive-living-0.jpg)
So I just went on my first primitive living practice trip in the woods, alone, with only a pocket knife.
So I just went on my first primitive living practice trip in the woods, alone,
with only a pocket knife.
I decided I'm going to share the lessons I've learned in each trip as they are certainly going to be useful if you want to practice primitive living, I would find these useful if I could find them anywhere. I spend a lot of time reading and watching primitive living guides and experience reports, but they are never exhaustive, and this series is not meant to be exhaustive either.
I decided I'm going to share the lessons I've learned in each trip as they are
certainly going to be useful if you want to practice primitive living, I would
find these useful if I could find them anywhere. I spend a lot of time reading
and watching primitive living guides and experience reports, but they are never
exhaustive, and this series is not meant to be exhaustive either.
<!--more-->
@ -22,21 +27,40 @@ Here we go:
# What I did know
I spent a lot of time studying about edible wild plants, how to butcher and cook different kinds of animals and insects. I also had practiced fire by friction and read a lot and watched videos about theory of making cordages, making a bow-drill and so on. I also knew and had already built shelters for the night. So you can assume I had a basic, broad understanding of the necessary skills, but experience? Not so much.
I spent a lot of time studying about edible wild plants, how to butcher and cook
different kinds of animals and insects. I also had practiced fire by friction
and read a lot and watched videos about theory of making cordages, making a
bow-drill and so on. I also knew and had already built shelters for the night.
So you can assume I had a basic, broad understanding of the necessary skills,
but experience? Not so much.
# Setup
I had a pocket knife, a Garmin GPS and a pocket first aid kid, I would expect something to go wrong along the way, so I thought I want to be safe, but not comfortable, that's why I brought emergency necessities, but not any comfort tools and materials. I also had a canned tuna for my first breakfast, but nothing more.
I had a pocket knife, a Garmin GPS and a pocket first aid kid, I would expect
something to go wrong along the way, so I thought I want to be safe, but not
comfortable, that's why I brought emergency necessities, but not any comfort
tools and materials. I also had a canned tuna for my first breakfast, but
nothing more.
Now for what is worth, I'm going in around summer's end, September 5th, in a forest in northern Iran, Mazandaran Province. The forest starts from foothills, covering a few mounts from both sides, so it's pretty large but also mountaneous, so I it's hard to move in the forest.
Now for what is worth, I'm going in around summer's end, September 5th, in a
forest in northern Iran, Mazandaran Province. The forest starts from foothills,
covering a few mounts from both sides, so it's pretty large but also
mountaneous, so I it's hard to move in the forest.
# Arrival: First Night
So I arrived at the entrace of the forest at night, it was already dark and I couldn't build a shelter or do much, I just slept on the open ground, it was my first night in the woods alone. I was quite scared at first, lots of cracks and movements in bushes by unknown creatures, but after a few hours I figured out all these creatures are small ones that can't be harmful to me. A few hours before dawn it got bitter cold, and I woke up, unable to go back to sleep. The first night was not the best, but could be worse.
So I arrived at the entrace of the forest at night, it was already dark and I
couldn't build a shelter or do much, I just slept on the open ground, it was my
first night in the woods alone. I was quite scared at first, lots of cracks and
movements in bushes by unknown creatures, but after a few hours I figured out
all these creatures are small ones that can't be harmful to me. A few hours
before dawn it got bitter cold, and I woke up, unable to go back to sleep. The
first night was not the best, but could be worse.
# First Day
I woke early at dawn and started moving into the forest, looking for a place to build my shelter in. I decided I'm going to follow these steps:
I woke early at dawn and started moving into the forest, looking for a place to
build my shelter in. I decided I'm going to follow these steps:
1. Build a shelter
2. Find water source
@ -49,60 +73,153 @@ But as was expected, it didn't go according to the plan.
## Shelter
I found a nice place to stay which had a stream passing by, the stream was running and from what I knew about the area, the water was safe to drink, so water was no longer an issue. I started building my shelter, got the base wooden structure down first, but there was a catch: I couldn't find any dry debris to put on top or inside. Last time I had built the same shelter it was autumn's end/early spring, so there were lots of dry, fallen leaves on the ground; But this time it's in the summer and there very few, scattered dry leaves on the ground, uncollectable.
I found a nice place to stay which had a stream passing by, the stream was
running and from what I knew about the area, the water was safe to drink, so
water was no longer an issue. I started building my shelter, got the base wooden
structure down first, but there was a catch: I couldn't find any dry debris to
put on top or inside. Last time I had built the same shelter it was autumn's
end/early spring, so there were lots of dry, fallen leaves on the ground; But
this time it's in the summer and there very few, scattered dry leaves on the
ground, uncollectable.
I decided I'm going with leaves of a small tree I had found nearby which seemed to be abundant around the area and the branches had lots of close leaves on them, looked like a good choice, but it was green. I didn't find out what I was doing wrong until I tried to sleep at night. The green leaves attracted lots of flies and insects and all sorts of annoying disturbances, and the smell wasn't helping either. I had to endure the insects throughout the night, because sleeping outside the shelter was a no-go, the dirt beneath was too cold. I hadn't put as much leaves on the ground, and the leaves were green (which also means they take more heat away), but still, it was much better than sleeping directly on the ground.
I decided I'm going with leaves of a small tree I had found nearby which seemed
to be abundant around the area and the branches had lots of close leaves on
them, looked like a good choice, but it was green. I didn't find out what I was
doing wrong until I tried to sleep at night. The green leaves attracted lots of
flies and insects and all sorts of annoying disturbances, and the smell wasn't
helping either. I had to endure the insects throughout the night, because
sleeping outside the shelter was a no-go, the dirt beneath was too cold. I
hadn't put as much leaves on the ground, and the leaves were green (which also
means they take more heat away), but still, it was much better than sleeping
directly on the ground.
What I learned was, **do not use green leaves for covering your shelter**. This rule applies to small shelters in which you are close to the covering, as well as the leaves you use as bedding. I've seen people using green leaves for covering big shelters which have a high ceiling, though I don't have any experience with those myself.
What I learned was, **do not use green leaves for covering your shelter**. This
rule applies to small shelters in which you are close to the covering, as well
as the leaves you use as bedding. I've seen people using green leaves for
covering big shelters which have a high ceiling, though I don't have any
experience with those myself.
![friction fire tries](/img/primitive-living-0-friction-fire.jpg)
## Friction Fire
The most important part of primitive living is fire, without fire you can't cook, you can't stay warm and you can't defy nocturnal predators. You also can't repel insects. You can't make a torch, so there goes an infinite list of fire applications that you will miss.
The most important part of primitive living is fire, without fire you can't
cook, you can't stay warm and you can't defy nocturnal predators. You also can't
repel insects. You can't make a torch, so there goes an infinite list of fire
applications that you will miss.
I knew the theory of friction fire in and out, how and why it works, but what I had missed was, **you are going to be in _real trouble_ if you can't find softwood**. To my surprise, searching portions of the forest, I couldn't find any softwood tree. Oaks were everywhere, as well as quite some other species of trees, but all of them were hardwood.
I knew the theory of friction fire in and out, how and why it works, but what I
had missed was, **you are going to be in _real trouble_ if you can't find
softwood**. To my surprise, searching portions of the forest, I couldn't find
any softwood tree. Oaks were everywhere, as well as quite some other species of
trees, but all of them were hardwood.
I tried different combinations of the softer woods I could find, but none of them resulted in an ember, I got smoke with one combination, but that was it. After about 5-6 hours of trying, I got real tired and gave up. By the way, I tried hand-drills, I couldn't succeed with bow-drills as I couldn't find suitable cordage, I tried with a promising bark that was pretty strong, but it would break as soon as I put some pressure on it, It's also possible that I might've gone wrong in making the bow itself, so it would cause the breakage.
I tried different combinations of the softer woods I could find, but none of
them resulted in an ember, I got smoke with one combination, but that was it.
After about 5-6 hours of trying, I got real tired and gave up. By the way, I
tried hand-drills, I couldn't succeed with bow-drills as I couldn't find
suitable cordage, I tried with a promising bark that was pretty strong, but it
would break as soon as I put some pressure on it, It's also possible that I
might've gone wrong in making the bow itself, so it would cause the breakage.
So the lesson was **make sure the material you are going to practice with is available in your practice area**, had I known there were no softwood in that particular forest, I would change my destination and probably succeed somewhere else. Sure, a professional survivalist must be able to start a fire in almost all situations, but this is practice and you have to start with easier steps.
So the lesson was **make sure the material you are going to practice with is
available in your practice area**, had I known there were no softwood in that
particular forest, I would change my destination and probably succeed somewhere
else. Sure, a professional survivalist must be able to start a fire in almost
all situations, but this is practice and you have to start with easier steps.
I ended up shaking for 2 hours before the dawn, not a pleasant experience at all. :D
I ended up shaking for 2 hours before the dawn, not a pleasant experience at
all. :D
## Food
The difficulties didn't end there, without a fire, my only hope for food was specific edible plants which can be eaten raw, or fruits. Unlucky as I was, I couldn't find a single fruit-bearing tree in the forest (I found quite a few fruit-bearing trees along the roads and paths to the forest, but not inside the forest itself), and I also couldn't find any of the other edible plants (I was mostly looking for the onion family) that I knew of.
The difficulties didn't end there, without a fire, my only hope for food was
specific edible plants which can be eaten raw, or fruits. Unlucky as I was, I
couldn't find a single fruit-bearing tree in the forest (I found quite a few
fruit-bearing trees along the roads and paths to the forest, but not inside the
forest itself), and I also couldn't find any of the other edible plants (I was
mostly looking for the onion family) that I knew of.
One of the greatest complications when starting primitive living practice anywhere other than the U.S. is that **almost all guides and materials on the topic are from, and for Northern America**. [The Falcon Guide to Edible Wild Plants](https://www.amazon.com/Edible-Wild-Plants-Falcon-Field/dp/0762774215) that I read is all about northern american plants. I knew it, but it's also the case that the Northern Hemisphere of the Earth have more common of an ecology, so most of the plants found in Northern America can also be found in places like Iran, but they have their differences. Most of the tips and tricks provided in different resources are for Northern American forests, which do not always work in other places.
One of the greatest complications when starting primitive living practice
anywhere other than the U.S. is that **almost all guides and materials on the
topic are from, and for Northern America**. [The Falcon Guide to Edible Wild
Plants](https://www.amazon.com/Edible-Wild-Plants-Falcon-Field/dp/0762774215)
that I read is all about northern american plants. I knew it, but it's also the
case that the Northern Hemisphere of the Earth have more common of an ecology,
so most of the plants found in Northern America can also be found in places like
Iran, but they have their differences. Most of the tips and tricks provided in
different resources are for Northern American forests, which do not always work
in other places.
So all in all, I ended up not eating anything for the next 24 hours, until I got out of the forest.
So all in all, I ended up not eating anything for the next 24 hours, until I got
out of the forest.
## Psychology
Apart from all the physical failures that I faced, which in turn caused frustration, I also had strong feelings of loneliness, boredom, and fear upon me. It was after failing to start a fire that I really felt the psychological burden on me. I had read about similar experiences, but believe me, the experience is hardly transmittable by words. A local rancher passing by the forest telling me about the leopard in the forest didn't make things any easier.
Apart from all the physical failures that I faced, which in turn caused
frustration, I also had strong feelings of loneliness, boredom, and fear upon
me. It was after failing to start a fire that I really felt the psychological
burden on me. I had read about similar experiences, but believe me, the
experience is hardly transmittable by words. A local rancher passing by the
forest telling me about the leopard in the forest didn't make things any easier.
The psychological pressure was above all other difficulties, at some point I was bursting into tears, but I couldn't associate it with any one specific feeling, it was a mix of anger, loneliness and fear.
The psychological pressure was above all other difficulties, at some point I was
bursting into tears, but I couldn't associate it with any one specific feeling,
it was a mix of anger, loneliness and fear.
Anger and frustration because I couldn't succeed in what I was trying to do. I also cut my finger at some point while carving the woods, so there was that.
Anger and frustration because I couldn't succeed in what I was trying to do. I
also cut my finger at some point while carving the woods, so there was that.
Loneliness because I was all by myself and I had no company to talk to. You can really actually go insane, as seen in [Cast Away](https://en.wikipedia.org/wiki/Cast_Away), after prolonged sessions of loneliness in situations like that. Mine wasn't long, it was only two days, but I still experienced the thought-fog, I couldn't think straight.
Loneliness because I was all by myself and I had no company to talk to. You can
really actually go insane, as seen in [Cast
Away](https://en.wikipedia.org/wiki/Cast_Away), after prolonged sessions of
loneliness in situations like that. Mine wasn't long, it was only two days, but
I still experienced the thought-fog, I couldn't think straight.
Fear because I felt weak compared to the power of nature, my fear was doubled by the fact that I was alone. I felt like being in a place where everything seems to know what it is doing, but I don't; I felt lost, not knowing what to do after my basic plans had failed.
Fear because I felt weak compared to the power of nature, my fear was doubled by
the fact that I was alone. I felt like being in a place where everything seems
to know what it is doing, but I don't; I felt lost, not knowing what to do after
my basic plans had failed.
Now I don't know if there is much you can do about the psychological part of it, I think experience is the remedy, at least I felt how different it was between the nights, the first night, even though I wasn't even _inside_ the forest much, I was almost at the border of it, it was much more creepy because it was my first time, but the second night, I was in the forest and now I had a _leopard_ in my mind pouncing on me, but I felt less fear and was more comfortable.
Now I don't know if there is much you can do about the psychological part of it,
I think experience is the remedy, at least I felt how different it was between
the nights, the first night, even though I wasn't even _inside_ the forest much,
I was almost at the border of it, it was much more creepy because it was my
first time, but the second night, I was in the forest and now I had a _leopard_
in my mind pouncing on me, but I felt less fear and was more comfortable.
But in the end, what helped me was that *I knew I was going to face a huge mental challenge along the way*, so I was more prepared. I think it's utterly important to be prepared for such psychological situations, knowing the reason behind your psychological challenges can help you overcome it to some extend.
But in the end, what helped me was that *I knew I was going to face a huge
mental challenge along the way*, so I was more prepared. I think it's utterly
important to be prepared for such psychological situations, knowing the reason
behind your psychological challenges can help you overcome it to some extend.
# Second Night
The second and last night was not all that much interesting, but it was damn sure cold and hard. At first I had to deal with the insects biting me everywhere and my feet scratching while trying to sleep in the shelter that I had wrongly built. After getting over that one and sleeping for what seemed to be ~2 hours, I woke up and felt the air temperature decreasing. I still got to sleep in intervals of 30 minutes until I woke up at around ~4 AM and my whole body was shaking. I couldn't do much, all I did was gather the leaves underneath a little closer and more dense, and crunch my body into a ball so I felt just a little warmer, but still shaking. It took ages for the last two and a half hours to pass until dawn. At dawn I got up quickly and walked around a little to warm myself up, and then waited until I could barely see my surroundings, then I started walking out of the forest.
The second and last night was not all that much interesting, but it was damn
sure cold and hard. At first I had to deal with the insects biting me everywhere
and my feet scratching while trying to sleep in the shelter that I had wrongly
built. After getting over that one and sleeping for what seemed to be ~2 hours,
I woke up and felt the air temperature decreasing. I still got to sleep in
intervals of 30 minutes until I woke up at around ~4 AM and my whole body was
shaking. I couldn't do much, all I did was gather the leaves underneath a little
closer and more dense, and crunch my body into a ball so I felt just a little
warmer, but still shaking. It took ages for the last two and a half hours to
pass until dawn. At dawn I got up quickly and walked around a little to warm
myself up, and then waited until I could barely see my surroundings, then I
started walking out of the forest.
Initially I had decided to stay for longer, but the weather forecast had predicted a heavy rain and storm for the next night, there was no way I could withstand that. :D
Initially I had decided to stay for longer, but the weather forecast had
predicted a heavy rain and storm for the next night, there was no way I could
withstand that. :D
# Bottom Line
It was a hard trip, I lost about 2kg (4lb) weight, but all in all the experience was a good one, I certainly learned a lot and I'm not going to make the same mistakes again. I should definitly practice more and keep working on my skills.
It was a hard trip, I lost about 2kg (4lb) weight, but all in all the experience
was a good one, I certainly learned a lot and I'm not going to make the same
mistakes again. I should definitly practice more and keep working on my skills.
If you are looking forward to practicing primitive living, please make sure you are safe and start small.
If you are looking forward to practicing primitive living, please make sure you
are safe and start small.
> Success is going from failure to failure without losing your enthusiasm. —Winston Churchill
> Success is going from failure to failure without losing your enthusiasm.
—Winston Churchill

View File

@ -7,24 +7,33 @@ excerpt_separator: <!--more-->
author: Mahdi
---
I just want to leave this here as I often tend to look it up myself and the first time it was not as easy to figure out.
I just want to leave this here as I often tend to look it up myself and the
first time it was not as easy to figure out.
When using Travis CI along with GitHub (or other git integrations), Travis runs two tests: <code>pr</code> and <code>push</code>.
When using Travis CI along with GitHub (or other git integrations), Travis runs
two tests: <code>pr</code> and <code>push</code>.
![travis-pr-push-github](/img/travis-ci-pr-push-github.jpg)
Most of the time you see both tests passing and you do not have to even wonder how they are different, but it has
happened to me that one of the tests fails while the other passes and I started to wonder why.
Most of the time you see both tests passing and you do not have to even wonder
how they are different, but it has happened to me that one of the tests fails
while the other passes and I started to wonder why.
### pr
The <code>pr</code> test is a test run on the result of a merge between the pull-request branch and the main branch.
As an example, let's say your pull-request's branch is called <code>fix-user-auth</code> and your main branch is <code>master</code>,
in this case, <code>pr</code> merges <code>fix-user-auth</code> into <code>master</code> and then runs the tests on the result of the merge.
### pr The <code>pr</code> test is a test run on the result of a merge between
the pull-request branch and the main branch. As an example, let's say your
pull-request's branch is called <code>fix-user-auth</code> and your main branch
is <code>master</code>, in this case, <code>pr</code> merges
<code>fix-user-auth</code> into <code>master</code> and then runs the tests on
the result of the merge.
### push
On the other hand, <code>push</code> is run on the pull-request branch itself, without merging. So in our example above, Travis would checkout to <code>fix-user-auth</code> and run the tests.
### push On the other hand, <code>push</code> is run on the pull-request branch
itself, without merging. So in our example above, Travis would checkout to
<code>fix-user-auth</code> and run the tests.
### A case of difference
A case in which this difference might be more apparent is when your pull-request is based on a branch other than <code>master</code>, and some changes that your pull-request depends on are missing from <code>master</code>, in this case the <code>push</code> test may pass, but the <code>pr</code> test will fail.
A case in which this difference might be more apparent is when your pull-request
is based on a branch other than <code>master</code>, and some changes that your
pull-request depends on are missing from <code>master</code>, in this case the
<code>push</code> test may pass, but the <code>pr</code> test will fail.

View File

@ -11,20 +11,34 @@ author: Mahdi
![a view of the stand + kindle](/img/kindle-stand/1.jpg)
I've had a Kindle for more than a year now, but I've only recently started to read books on it frequently, I used to read paperworks before that, and I still do sometimes prefer paperbooks if available. Anyways, my Kindle has helped me to fall asleep without struggling with all my thoughts, all I have to do is read until I fall asleep, so in a way, it has also been a remedy for my insomnia.
I've had a Kindle for more than a year now, but I've only recently started to
read books on it frequently, I used to read paperworks before that, and I still
do sometimes prefer paperbooks if available. Anyways, my Kindle has helped me to
fall asleep without struggling with all my thoughts, all I have to do is read
until I fall asleep, so in a way, it has also been a remedy for my insomnia.
Now to read the Kindle in bed, you would have to hold it using your hands or buy a stand or make one, motivated by [The Pursuit of Laziness](https://blog.xkcd.com/2009/04/13/the-pursuit-of-laziness/) I set to create mine, but I didn't use a piece of steel, instead I used a single box of cardboard I had in home to create one in minutes. :D
Now to read the Kindle in bed, you would have to hold it using your hands or buy
a stand or make one, motivated by [The Pursuit of
Laziness](https://blog.xkcd.com/2009/04/13/the-pursuit-of-laziness/) I set to
create mine, but I didn't use a piece of steel, instead I used a single box of
cardboard I had in home to create one in minutes. :D
<!--more-->
It's too easy to need much of an instruction, a few pictures and some explanation will do:
It's too easy to need much of an instruction, a few pictures and some
explanation will do:
![a view of the stand without kindle](/img/kindle-stand/0.jpg)
So this part shows a simple piece of cardboard cut using scissors on the front, with the sides taped to the bottom (actually if your piece of cardboard is a box, it might already be taped in that way, mine was).
So this part shows a simple piece of cardboard cut using scissors on the front,
with the sides taped to the bottom (actually if your piece of cardboard is a
box, it might already be taped in that way, mine was).
![a view of the stand's back side](/img/kindle-stand/2.jpg)
On the back, there is another piece of cardboard (I took the opening of it which already had a notch line, and the size fit perfectly). I used a stapler to to attach the two sides toghether, and that's it!
On the back, there is another piece of cardboard (I took the opening of it which
already had a notch line, and the size fit perfectly). I used a stapler to to
attach the two sides toghether, and that's it!
I tried it last night to make sure it's convenient before posting here, and I tell you, it is totally comfortable and much better than holding with a hand.
I tried it last night to make sure it's convenient before posting here, and I
tell you, it is totally comfortable and much better than holding with a hand.

View File

@ -11,9 +11,17 @@ toc: true
author: Mahdi
---
I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html). There I stumbled upon [Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments!
I wanted to get proficient in Haskell so I decided to follow [An [Essential]
Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html).
There I stumbled upon
[Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material
is great, I couldn't find solutions for the exercises to check against, so I
decided I would write my own and hopefully the solutions would get fixed in case
I have gone wrong by others. So if you think a solution is wrong, let me know in
the comments!
In each section below, I left some reference material for the exercises and then the solutions.
In each section below, I left some reference material for the exercises and then
the solutions.
Note: The post will be updated as I progress in Typoclassopedia myself
@ -34,9 +42,19 @@ instance Functor Maybe where
fmap g (Just a) = Just (g a)
```
> ((,) e) represents a container which holds an “annotation” of type e along with the actual value it holds. It might be clearer to write it as (e,), by analogy with an operator section like (1+), but that syntax is not allowed in types (although it is allowed in expressions with the TupleSections extension enabled). However, you can certainly think of it as (e,).
> ((,) e) represents a container which holds an “annotation” of type e along
with the actual value it holds. It might be clearer to write it as (e,), by
analogy with an operator section like (1+), but that syntax is not allowed in
types (although it is allowed in expressions with the TupleSections extension
enabled). However, you can certainly think of it as (e,).
> ((->) e) (which can be thought of as (e ->); see above), the type of functions which take a value of type e as a parameter, is a Functor. As a container, (e -> a) represents a (possibly infinite) set of values of a, indexed by values of e. Alternatively, and more usefully, ((->) e) can be thought of as a context in which a value of type e is available to be consulted in a read-only fashion. This is also why ((->) e) is sometimes referred to as the reader monad; more on this later.
> ((->) e) (which can be thought of as (e ->); see above), the type of functions
which take a value of type e as a parameter, is a Functor. As a container, (e ->
a) represents a (possibly infinite) set of values of a, indexed by values of e.
Alternatively, and more usefully, ((->) e) can be thought of as a context in
which a value of type e is available to be consulted in a read-only fashion.
This is also why ((->) e) is sometimes referred to as the reader monad; more on
this later.
### Exercises
@ -66,7 +84,9 @@ instance Functor Maybe where
```
Their similarity is in the fact that they both represent types of two values.
Their difference is that `((,) e)` (tuples of two) can have values of different types (kind of `(,)` is `* -> *`) while both values of `Pair` have the same type `a`, so `Pair` has kind `*`.
Their difference is that `((,) e)` (tuples of two) can have values of
different types (kind of `(,)` is `* -> *`) while both values of `Pair` have
the same type `a`, so `Pair` has kind `*`.
3. Implement a `Functor` instance for the type `ITree`, defined as
@ -105,7 +125,8 @@ instance Functor Maybe where
[16, 12, 12]
```
4. Give an example of a type of kind `* -> *` which cannot be made an instance of `Functor` (without using `undefined`).
4. Give an example of a type of kind `* -> *` which cannot be made an instance
of `Functor` (without using `undefined`).
I don't know the answer to this one yet!
@ -113,7 +134,8 @@ instance Functor Maybe where
> The composition of two `Functor`s is also a `Functor`.
If false, give a counterexample; if true, prove it by exhibiting some appropriate Haskell code.
If false, give a counterexample; if true, prove it by exhibiting some
appropriate Haskell code.
**Solution**:
@ -141,7 +163,10 @@ fmap (g . h) = (fmap g) . (fmap h)
### Exercises
1. Although it is not possible for a Functor instance to satisfy the first Functor law but not the second (excluding undefined), the reverse is possible. Give an example of a (bogus) Functor instance which satisfies the second law but not the first.
1. Although it is not possible for a Functor instance to satisfy the first
Functor law but not the second (excluding undefined), the reverse is
possible. Give an example of a (bogus) Functor instance which satisfies the
second law but not the first.
**Solution**:
@ -161,7 +186,8 @@ fmap (g . h) = (fmap g) . (fmap h)
λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5]
```
2. Which laws are violated by the evil Functor instance for list shown above: both laws, or the first law alone? Give specific counterexamples.
2. Which laws are violated by the evil Functor instance for list shown above:
both laws, or the first law alone? Give specific counterexamples.
```haskell
-- Evil Functor instance
@ -178,7 +204,9 @@ fmap (g . h) = (fmap g) . (fmap h)
Category Theory
===============
The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Haskell/Category_theory), so here I'm going to cover the exercises of that page, too.
The Functor section links to [Category
Theory](https://en.wikibooks.org/wiki/Haskell/Category_theory), so here I'm
going to cover the exercises of that page, too.
## Introduction to categories
@ -188,17 +216,26 @@ The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Has
$f \circ (g \circ h) = (f \circ g) \circ h$
2. The category needs to be **closed** under the composition operator. So if $f : B \to C$ and $g: A \to B$, then there must be some $h: A \to C$ in the category such that $h = f \circ g$.
3. Every object $A$ in a category must have an identity morphism, $id_A : A \to A$ that is an identity of composition with other morphisms. So for every morphism $g: A \to B$:
2. The category needs to be **closed** under the composition operator. So if $f
: B \to C$ and $g: A \to B$, then there must be some $h: A \to C$ in the
category such that $h = f \circ g$.
3. Every object $A$ in a category must have an identity morphism, $id_A : A \to
A$ that is an identity of composition with other morphisms. So for every
morphism $g: A \to B$:
$g \circ id_A = id_B \circ g = g$.
### Exercises
1. As was mentioned, any partial order $(P, \leq)$ is a category with objects as the elements of P and a morphism between elements a and b iff $a \leq b$. Which of the above laws guarantees the transitivity of $\leq$?
1. As was mentioned, any partial order $(P, \leq)$ is a category with objects as
the elements of P and a morphism between elements a and b iff $a \leq b$.
Which of the above laws guarantees the transitivity of $\leq$?
**Solution**:
The second law, which states that the category needs to be closed under the composition operator guarantess that because we have a morphism $a \leq b$, and another morphism $b \leq c$, there must also be some other morphism such that $a \leq c$.
The second law, which states that the category needs to be closed under the
composition operator guarantess that because we have a morphism $a \leq b$,
and another morphism $b \leq c$, there must also be some other morphism such
that $a \leq c$.
2. If we add another morphism to the above example, as illustrated below, it fails to be a category. Why? Hint: think about associativity of the composition operation.
@ -226,7 +263,8 @@ The Functor section links to [Category Theory](https://en.wikibooks.org/wiki/Has
### Functor laws:
<