<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="14084" data-post-id="14084">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="keathley" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/keathley/120/2652_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  keathley
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The papers on dialyzer and success types include a lot of the pitfalls in trying to build an ML type system for Erlang: <a href="https://it.uu.se/research/group/hipe/papers/succ_types.pdf" class="inline-onebox" rel="noopener nofollow ugc">Research groups – Department of Information Technology – Uppsala University</a>.</p>
<p><a class="mention" href="/u/overminddl1" rel="nofollow">@OvermindDL1</a> Have you looked into multi-party session types? <a href="http://groups.inf.ed.ac.uk/abcd/index.html" class="inline-onebox" rel="noopener nofollow ugc">From Data Types to Session Types: A Basis for Concurrency and Distribution</a>. That research seems like it could be a promising way forward.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="14084" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-14084" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="14084"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="14090" data-post-id="14090">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="DianaOlympos" data-post="10" data-topic="1388" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dianaolympos/48/4353_2.png" class="avatar"> DianaOlympos:</div>
<blockquote>
<p>Just so you know, the problem Philip Wadler found when he tried to type erlang :</p>
<ul>
<li>message</li>
<li>pid and process in particular self ()</li>
</ul>
<p>The other question is… how do you deal with distributed message. You can get a message from a node that do not follow the comtract you assigned. So your type checking is useless in that case…</p>
</blockquote>
</aside>
<p>Already have a test library for that (in OCaml).  A quick overview:<br>
Message is just typed as <code>Erlang.t</code>, which is a blackbox unknown erlang type.<br>
Pid is an <code>Erlang.Pid.t</code>, which is also a blackbox erlang type that you know is a pid, you can do something like <code>Erlang.Pid.send somePid someMessage</code> as an example.</p>
<p>The <code>Erlang</code> module would have testing like <code>Erlang.is_int something</code> as well as reifiers like <code>Erlang.reify something</code> that can be used like:</p>
<pre data-code-wrap="ocaml"><code class="lang-ocaml">let open Erlang in
match reify something with
| Int i -&gt; doSomethingWithInt i
| Binary b -&gt; doSomethingWithBinary b
| Tuple [ Int i; Float f ] -&gt; doSomethingWithIntAndFloat i f
| _ -&gt; doSomethingAsDefaultCase
</code></pre>
<p>Or so forth, and those are only the primitives, can build up better matchers on top of that pretty easily (including dynamically creating arbitrary depth decoders based on types of, say, a <code>receive</code> call).  This is pretty easy to do in OCaml and I already have this part done (as I was playing around to see how easy it is).  I was planning something similar in this once I figured up a good API but I do think I’d end up having to enforce a new language or so…</p>
<aside class="quote no-group" data-username="michalmuskala" data-post="11" data-topic="1388" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/michalmuskala/48/20288_2.png" class="avatar"> michalmuskala:</div>
<blockquote>
<p>Another thing that makes typing erlang/elixir really difficult is dynamic loading of modules. The function you’re using may actually not exist yet when you’re writing it, the module may be loaded later. Not to mention hot upgrades that completely mess stuff up.</p>
</blockquote>
</aside>
<p>Eyup, this would only typecheck at compile-time, at runtime it would all still be elixir and you gotta deal with the changes you make, if you do non-atomic hot code swapping and you change your API, then just like in normal erlang be prepared to deal with the consequences (and exceptions, :EXIT’s, etc…).  This is less to ensure safety at runtime (erlang does that pretty well already) and more to help ensure that I do not screw up at compile-time by passing things in the wrong order or so, that is my primary use of statically typed languages.  Trying to statically type it all at runtime is a fools errand and not something I would even attempt except for occasionally throwing in <code>is_int</code>’s or so in <code>when</code> clauses.  I want something to help me code, not ensure safety at runtime (as stated, erlang does that well enough itself via OTP).</p>
<aside class="quote no-group quote-modified" data-username="keathley" data-post="12" data-topic="1388">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/keathley/48/2652_2.png" class="avatar"> keathley:</div>
<blockquote>
<p>The papers on dialyzer and success types include a lot of the pitfalls in trying to build an ML type system for Erlang: <a href="https://it.uu.se/research/group/hipe/papers/succ_types.pdf" class="inline-onebox" rel="noopener nofollow ugc">Research groups – Department of Information Technology – Uppsala University</a>.</p>
</blockquote>
</aside>
<p>Yeah I ran across that long ago, and is one of the reasons I started by thinking of a way to black-box a type like my above <code>Erlang.t</code> type, that way I can always fall back to that and force the user (I.E. me) to do proper tests to reify it and use what they want and handle the cases where they get what they do not want.</p>
<aside class="quote no-group quote-modified" data-username="keathley" data-post="12" data-topic="1388">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/keathley/48/2652_2.png" class="avatar"> keathley:</div>
<blockquote>
<p><a class="mention" href="/u/overminddl1" rel="nofollow">@OvermindDL1</a> Have you looked into multi-party session types? <a href="http://groups.inf.ed.ac.uk/abcd/index.html" class="inline-onebox" rel="noopener nofollow ugc">From Data Types to Session Types: A Basis for Concurrency and Distribution</a>. That research seems like it could be a promising way forward.</p>
</blockquote>
</aside>
<p>Hmm, that is not something I’ve come across, seems like a decoder of the <code>Erlang.t</code> type could fit within that, it either succeeds or fails given a pattern, which is defined manually if you wish like:</p>
<pre data-code-wrap="ocaml"><code class="lang-ocaml">let myDecoder =
  let open Erlang.Decoders in
  Tuple
    [ Literal.Atom `Something
    ; Atom
    ; Validate Int (fun i -&gt; i &gt;= 0 &amp;&amp; i &lt; 10)
    ; Binary
    ]

(* Use it like: *)
match Erlang.Decoders.decode myDecoder something with
| Some (_, someAtom, someInt, someBinary) -&gt; doSomething someAtom someInt someBinary
| Error _e -&gt; ()
</code></pre>
<p>Which in Elixir would be the same as:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case something do
  (:Something, someAtom, someInt, someBinary) when
    is_atom(someAtom) and
    is_int(someInt) and
    is_binary(someBinary) and
    someInt&gt;=0 and someInt&lt;10 -&gt;
      doSomething(someAtom, someInt, someBinary)
  _ -&gt; nil
end
</code></pre>
<p>Thus modules can define decoders (and with mapping and such can transform the data as well during decoding) that can be used elsewhere to parse data.  If I made an ocaml backend (I would so love to get the time for that!) then <code>reify</code> could reify a whole tree so you could match on something like this as well:</p>
<pre data-code-wrap="ocaml"><code class="lang-ocaml">let rec blah something v in
  let open Erlang in
  match Erlang.reify something with
  | Tuple [ Atom `Something; Int i ] -&gt; i + v
  | List [] -&gt; v
  | List (Int i :: rest) when i&lt;10 -&gt; blah rest (i + v)
  | _ -&gt; v
</code></pre>
<p>Which in Elixir would be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def blah something v do
  case something do
    (:Something, i) when is_int(i) -&gt; i + v
    [] -&gt; v
    [i | rest] when is_int(i) and i&lt;10 -&gt; blah(rest, v + i)
  end
end
</code></pre>
<p>In both cases it is just a function that can take a tuple of `(:Something, 42) or a list of integers that it will then sum up each element if the element is less than 10 (OCaml has ‘when’ like in Erlang/Elixir in its pattern matching too).</p>
<p>I’m pretty sure I’ve worked around each usual issue that would happen by having a statically typed language compile to Erlang/Elixir, although it would be slightly more wordy what with things like the <code>Erlang.reify</code> work and such.  But for something like receive you can pass in a decoder (that can decode a variety of types, I modeled it on Elm’s JSON Decoders/Encoders) to get back a specific type or could just call it with an <code>identity</code> to get back the next message as an opaque type that you can then match on to unconditionally remove from the mailbox anyway.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="14090" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-14090" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="14090"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="24587" data-post-id="24587">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>An update after <em>months</em>!</p>
<p>So far these all work as expected, it uses types and spec’s when it can, and infer’s it otherwise when it cannot (or complains):</p>
<pre data-code-wrap="iex"><code class="lang-iex">iex&gt; use TypedElixir
TypedElixir

iex&gt; defmodulet TypedTest_Empty do
...&gt; end
{:module, TypedTest_Empty,
 &lt;&lt;70, 79, 82, 49, 0, 0, 3, 244, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 94,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, nil}

iex&gt; defmodulet TypedTest_Typed_Simple do
...&gt;   @spec simple() :: nil
...&gt;   def simple(), do: nil
...&gt; end
{:module, TypedTest_Typed_Simple,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 196, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 129,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:simple, 0}}
iex&gt; TypedTest_Typed_Simple.simple()
nil

iex&gt; defmodulet TypedTest_Untyped_Simple do
...&gt;   def simple(), do: nil
...&gt; end
{:module, TypedTest_Untyped_Simple,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 176, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 129,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:simple, 0}}
iex&gt; TypedTest_Untyped_Simple.simple()
nil

iex&gt; defmodulet TypedTest_Untyped_Recursive_Simple_BAD_NoSet do
...&gt;   def simple(), do: simple()
...&gt;   def willFail() do
...&gt;     x = simple()
...&gt;   end
...&gt; end
** (throw) {:INVALID_ASSIGNMENT_NOT_ALLOWED, :no_return}
    (typed_elixir) lib/typed_elixir.ex:232: TypedElixir.type_check_expression/3
    (typed_elixir) lib/typed_elixir.ex:198: TypedElixir.type_check_def_body/3
    (typed_elixir) lib/typed_elixir.ex:121: TypedElixir.type_check_body/3
    (typed_elixir) lib/typed_elixir.ex:104: anonymous fn/3 in TypedElixir.typecheck_module/4
          (elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
    (typed_elixir) lib/typed_elixir.ex:103: TypedElixir.typecheck_module/4
    (typed_elixir) expanding macro: TypedElixir.defmodulet/2
                   iex:5: (file)
iex&gt; # Cannot set the return value of a function that never returns...
nil

iex&gt; # The extra type is to give a name to the type in simple, so the input and output become the same type.
nil
iex&gt; # If the spec was `simple(any()) :: any()` then you could not state that the output type is based on the input type.
nil
iex&gt; defmodulet TypedTest_Typed_Identity do
...&gt;   @type identity_type :: any()
...&gt;   @spec identity(identity_type) :: identity_type
...&gt;   def identity(x), do: x
...&gt; end
{:module, TypedTest_Typed_Identity,
 &lt;&lt;70, 79, 82, 49, 0, 0, 5, 48, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 191,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:identity, 1}}
iex&gt; TypedTest_Typed_Identity.identity(42)
42
iex&gt;
nil

iex&gt; defmodulet TypedTest_Typed_Identity_badtype do
...&gt;   @type identity_type :: any()
...&gt;   @spec identity(identity_type) :: identity_type
...&gt;   def identity(_x), do: nil
...&gt; end
** (throw) {:NO_TYPE_RESOLUTION, %TypedElixir.Type.Const{const: :atom, meta: %{values: [nil]}}, %TypedElixir.Type.Ptr.Generic{id: 0, named: true}}
    (typed_elixir) lib/typed_elixir.ex:514: TypedElixir.resolve_types_nolinks/3
    (typed_elixir) lib/typed_elixir.ex:454: TypedElixir.resolve_types!/3
    (typed_elixir) lib/typed_elixir.ex:168: TypedElixir.resolve_fun_return_type_/4
    (typed_elixir) lib/typed_elixir.ex:146: TypedElixir.resolve_fun_return_type/4
    (typed_elixir) lib/typed_elixir.ex:127: TypedElixir.type_check_body/3
    (typed_elixir) lib/typed_elixir.ex:104: anonymous fn/3 in TypedElixir.typecheck_module/4
          (elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
    (typed_elixir) lib/typed_elixir.ex:103: TypedElixir.typecheck_module/4
iex&gt; # Since it is a named type the input and output must match
nil

iex&gt; defmodulet TypedTest_Typed_Identity_AnyReturn do
...&gt;   @spec identity(any()) :: any()
...&gt;   def identity(_x), do: nil
...&gt; end
{:module, TypedTest_Typed_Identity_AnyReturn,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 248, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 152,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:identity, 1}}
iex&gt; TypedTest_Typed_Identity_AnyReturn.identity(42)
nil
iex&gt; # An unnamed `any()` means it can literally return anything, the input does not matter
nil

iex&gt; defmodulet TypedTest_Untyped_Identity do
...&gt;   def identity(x), do: x
...&gt; end
{:module, TypedTest_Untyped_Identity,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 204, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 149,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:identity, 1}}
iex&gt; TypedTest_Untyped_Identity.identity(42)
42

iex&gt; defmodulet TypedTest_Untyped_Identity_AnyReturn do
...&gt;   def identity(_x), do: nil
...&gt; end
{:module, TypedTest_Untyped_Identity_AnyReturn,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 236, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 152,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:identity, 1}}
iex&gt; TypedTest_Untyped_Identity_AnyReturn.identity(42)
nil
iex&gt; # Since it is not typed it gets an inferred return value of `nil`
nil

iex&gt; defmodulet TypedTest_Typed_Recursive_Counter do
...&gt;   @spec counter(integer()) :: integer()
...&gt;   def counter(x), do: counter(x)
...&gt; end
{:module, TypedTest_Typed_Recursive_Counter,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 248, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 148,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:counter, 1}}
iex&gt; # Not calling it because infinite recursion...
nil

iex&gt; defmodulet TypedTest_Untyped_Recursive_Counter do
...&gt;   def counter(x), do: counter(x)
...&gt; end
{:module, TypedTest_Untyped_Recursive_Counter,
 &lt;&lt;70, 79, 82, 49, 0, 0, 4, 224, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 148,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:counter, 1}}
iex&gt; # Again, not calling it because infinite recursion...

iex&gt; defmodulet TypedTest_Typed_Recursive_Counter_Bad do
...&gt;   @spec counter(integer()) :: integer()
...&gt;   def counter(x), do: counter(6.28)
...&gt; end
** (throw) {:NO_TYPE_UNIFICATION, :NO_PATH, %TypedElixir.Type.Const{const: :integer, meta: %{}}, %TypedElixir.Type.Const{const: :float, meta: %{values: [6.28]}}}
    (typed_elixir) lib/typed_elixir.ex:567: TypedElixir.unify_types_nolinks/3
    (typed_elixir) lib/typed_elixir.ex:521: TypedElixir.unify_types!/3
          (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (typed_elixir) lib/typed_elixir.ex:250: TypedElixir.type_check_expression/3
    (typed_elixir) lib/typed_elixir.ex:201: TypedElixir.type_check_def_body/3
    (typed_elixir) lib/typed_elixir.ex:121: TypedElixir.type_check_body/3
    (typed_elixir) lib/typed_elixir.ex:104: anonymous fn/3 in TypedElixir.typecheck_module/4
          (elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3


iex&gt; defmodulet TypedTest_Untyped_Recursive_Counter_RecallingDifferentType do
...&gt;   def counter(_x), do: counter(6.28)
...&gt; end
{:module, TypedTest_Untyped_Recursive_Counter_RecallingDifferentType,
 &lt;&lt;70, 79, 82, 49, 0, 0, 5, 56, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 151,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;, {:counter, 1}}
iex&gt; # Not calling this either, infinite recursion
nil

iex&gt; defmodulet TypedTest_Typed_MultiFunc0 do
...&gt;   @spec simple() :: nil
...&gt;   def simple(), do: nil
...&gt; 
...&gt;   @type identity_type :: any()
...&gt;   @spec identity(identity_type) :: identity_type
...&gt;   def identity(x), do: x
...&gt; 
...&gt;   @spec call_simple(any()) :: any()
...&gt;   def call_simple(_x), do: simple()
...&gt; 
...&gt;   @spec call_simple_constrain_to_nil(any()) :: nil
...&gt;   def call_simple_constrain_to_nil(_x), do: simple()
...&gt; 
...&gt;   @spec call_simple_through_identity(any()) :: nil
...&gt;   def call_simple_through_identity(_x), do: simple() |&gt; identity()
...&gt; end
{:module, TypedTest_Typed_MultiFunc0,
 &lt;&lt;70, 79, 82, 49, 0, 0, 7, 232, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 1, 167,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...&gt;&gt;,
 {:call_simple_through_identity, 1}}
iex&gt; TypedTest_Typed_MultiFunc0.call_simple_through_identity(42)
nil
iex&gt; TypedTest_Typed_MultiFunc0.call_simple(42)
nil
iex&gt; TypedTest_Typed_MultiFunc0.identity(42)
42
iex&gt; # call_simple_through_identity is properly typed with a return of nil as you notice
nil
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="24587" data-batch-url="/posts/batch_likers">
                        11
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-24587" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="24587"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="118304" data-post-id="118304">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pro_actor" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pro_actor/120/18107_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pro_actor
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks for your work, it would be extremely great to elixir to have static type system!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="118304" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-118304" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="118304"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="118720" data-post-id="118720">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Gradualizer is similar but it operates on the BEAM opcode level, so it both has more and less information in different ways.  I can’t wait for a full release!  <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="118720" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-118720" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="118720"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="124081" data-post-id="124081">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Exadra37" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Exadra37/120/9183_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Exadra37
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>So you gave up of your approach in favor of <a href="https://github.com/josefs/Gradualizer" rel="noopener nofollow ugc">Gradualizer</a>?</p>
<p>I really miss having a type system in Elixir. I know we have Dialyzer, but is not the same and is not straight forward to use.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="124081" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-124081" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="124081"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="124261" data-post-id="124261">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Phillipp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Phillipp/120/10625_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Phillipp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I actually not miss a type system in Elixir. I absolutely hate having to work with Typescript at some work projects and wish I had Elixirs pattern matching. I guess it’s just personal preference. That said, if Elixir ever forced a type system on me, I would not use it anymore.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="124261" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-124261" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="124261"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
    <div class="postbit" id="124331" data-post-id="124331">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Exadra37" data-post="20" data-topic="1388">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/exadra37/48/9183_2.png" class="avatar"> Exadra37:</div>
<blockquote>
<p>So you gave up of your approach in favor of <a href="https://github.com/josefs/Gradualizer" rel="noopener nofollow ugc">Gradualizer </a>?</p>
</blockquote>
</aside>
<p>Not really, I’d love to make a typed-elixir style system, I just don’t have time, at all…  ^.^;</p>
<aside class="quote no-group" data-username="Exadra37" data-post="20" data-topic="1388">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/exadra37/48/9183_2.png" class="avatar"> Exadra37:</div>
<blockquote>
<p>I really miss having a type system in Elixir. I know we have Dialyzer, but is not the same and is not straight forward to use.</p>
</blockquote>
</aside>
<p>I entirely agree!  A full and proper type system is not just for static type checking but for lots of other reasons as well, like code disambiguation, code generation based on types, etc… etc…</p>
<aside class="quote no-group" data-username="Phillipp" data-post="21" data-topic="1388" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/phillipp/48/10625_2.png" class="avatar"> Phillipp:</div>
<blockquote>
<p>I actually not miss a type system in Elixir. I absolutely hate having to work with Typescript at some work projects and wish I had Elixirs pattern matching. I guess it’s just personal preference. That said, if Elixir ever forced a type system on me, I would not use it anymore.</p>
</blockquote>
</aside>
<p>Typescript is… not really a great example of a type system, it’s awfully verbose.  <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="124331" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-124331" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="124331"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
    <div class="postbit" id="124336" data-post-id="124336">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Exadra37" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Exadra37/120/9183_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Exadra37
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I completely agree with you… It enables more confidence in how we code, less tests, and less code to check for stuff that should be work of the compiler or runtime.</p>
<p>I am looking forward to see how <a class="hashtag-cooked" href="/tag/gleam/2298" data-type="tag" data-slug="gleam" data-id="2298" data-style-type="icon" data-icon="tag" rel="nofollow"><span class="hashtag-icon-placeholder"><svg class="fa d-icon d-icon-square-full svg-icon svg-node"><use href="#square-full"></use></svg></span><span>gleam</span></a> by <a class="mention" href="/u/lpil" rel="nofollow">@lpil</a>  will develop <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="124336" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-124336" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="124336"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="130091" data-post-id="130091">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pera" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pera/120/10542_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pera
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>So… <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20">  why is nobody talking about this two recently published papers on <strong>session types</strong>?:</p>
<ul>
<li><a href="http://simonjf.com/writing/zap.pdf" rel="noopener nofollow ugc">Exceptional Asynchronous Session Types - Session Types without Tiers</a> [pdf]</li>
<li><a href="https://www.doc.ic.ac.uk/~ascalas/papers/scalas-yoshida-popl19.pdf" rel="noopener nofollow ugc">Less Is More: Multiparty Session Types Revisited</a> [pdf]</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="130091" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/typed-elixir/1388/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-130091" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="130091"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/1388/load_more?page=3">Load more posts (8 remaining)</a>
</div></template></turbo-stream>