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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="NobbZ" data-post="21" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nobbz/48/27235_2.png" class="avatar"> NobbZ:</div>
<blockquote>
<p>Though indeed I would have prefered if there was a name on the type line that tells me for what it actually is, to get a warning when after “code juggling” annotations get moved away from their functions…</p>
</blockquote>
</aside>
<p>I’d imagine you’d get a compilation error if you moved a function away and have a type line annotating either nothing or an incompatible function.  Otherwise, there’s certainly no harm in accidentally forgetting to move the type lines for functions that have the same signature.  Am I missing a scenario?</p>
<p>EDIT: sorry, you said it the other way around.  I getcha now.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="366951" 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/a-case-for-inline-type-annotations/71220/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-366951" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="366951"
                     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="366963" data-post-id="366963">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I like the <code>@def</code> for that reason. I thought of it myself but I’d rather not have an equivalent <code>@defp</code>, the annotations should be the same event if the function is exposed.</p>
<p>Actually I like Erlangs way of exporting functions better, and have never been a fan of Elixir’s syntax (despite being my favorite language). Syntax is not very important but yes, having the function name in the annotation would be time saving (also because you may group them at the top of the file).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="366963" 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/a-case-for-inline-type-annotations/71220/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-366963" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="366963"
                     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="367016" data-post-id="367016">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="smueller" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/120/3857_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  smueller
                    <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="lud" data-post="11" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lud/48/14382_2.png" class="avatar"> lud:</div>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI.t() | String.t() | nil) :: String.t() | nil, do: host
def hostname(url :: URI.t() | String.t() | nil) when is_binary(url) :: String.t() | nil, do: hostname(URI.parse(url))
def hostname(nil :: URI.t() | String.t() | nil) :: String.t() | nil, do: nil
</code></pre>
</blockquote>
</aside>
<p>Using Rust, Typescript, Kotlin, and Swift for inspiration, this could be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI | String?) :: String?, do: host
def hostname(url :: URI | String?) when is_binary(url) :: String?, do: hostname(URI.parse(url))
def hostname(nil :: URI | String?) :: String?, do: nil
</code></pre>
<p>And now there’s no question of readability, which furthers my point: modern languages have already solved this elegantly and concisely.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367016" 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/a-case-for-inline-type-annotations/71220/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-367016" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367016"
                     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>
    <div class="postbit" id="367017" data-post-id="367017">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="smueller" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/120/3857_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  smueller
                    <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 group-livebook_core_team" data-username="josevalim" data-post="12" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>One of the goals of the type system is to allow us to say that, if we add a new payment status, the code above should emit a warning. In this case, it doesn’t make sense to annotate inline, because each clause only handles part of the payments, and you want to guarantee it handles all statuses as a whole:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ payment_status() -&gt; ...
def log_payment_status(:trial) do
def log_payment_status({:success, metadata}) do
def log_payment_status({:overdue, metadata}) do
</code></pre>
</blockquote>
</aside>
<p>Always appreciate you taking the time to chime in, Jose <img src="https://forum.elixirforum.com/images/emoji/apple/folded_hands.png?v=15" title=":folded_hands:" class="emoji" alt=":folded_hands:" loading="lazy" width="20" height="20"></p>
<p>You’re making a case for type aliases, which is not a mutually exclusive concept to inline types. In your example, imagine:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ typealias PaymentStatus = :trial | {:success, metadata} | {:overdue, metadata}
def log_payment_status(:trial :: PaymentStatus) do
def log_payment_status({:success, metadata} :: PaymentStatus) do
def log_payment_status({:overdue, metadata} :: PaymentStatus) do
</code></pre>
<p>Which is the best of both worlds: an explicitly defined function with inline typing, while maintaining a clean and readable signature.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="12" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Modern and ergonomic is not about copying what other languages do, is about making sure it fits with the existing patterns and idioms in the language. <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>
</blockquote>
</aside>
<p>This conversation is not about blindly copying other languages. It’s about the history of language syntax and where we’re at in 2025 – there are now concepts that clearly have consensus. I think optional types (e.g. <code>String?</code>) and inline typing have consensus, and should be heavily considered (if technologically possible in elixir).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367017" 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/a-case-for-inline-type-annotations/71220/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-367017" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367017"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="367019" data-post-id="367019">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="smueller" data-post="25" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/48/3857_2.png" class="avatar"> smueller:</div>
<blockquote>
<p>You’re making a case for type aliases, which is not a mutually exclusive concept to inline types.</p>
</blockquote>
</aside>
<p>I think you might have missed:</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="12" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p><code>$ type payment_status = :trial | {:success, metadata} | {:overdue, metadata}</code></p>
</blockquote>
</aside>
<aside class="quote no-group" data-username="smueller" data-post="24" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/48/3857_2.png" class="avatar"> smueller:</div>
<blockquote>
<p>And now there’s no question of readability, which furthers my point: modern languages have already solved this elegantly and concisely.</p>
</blockquote>
</aside>
<p>Even with that fairly trivial example, having the type signature defined three times is not exactly what I’d call concise. It also triples the work to keep the type signature correct with any refactoring, and increases the surface area for mistakes, IMO.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367019" data-batch-url="/posts/batch_likers">
                        8
                      </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/a-case-for-inline-type-annotations/71220/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-367019" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367019"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="367020" data-post-id="367020">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="smueller" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/120/3857_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  smueller
                    <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="jswanner" data-post="26" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jswanner/48/24585_2.png" class="avatar"> jswanner:</div>
<blockquote>
<p>I think you might have missed:</p>
</blockquote>
</aside>
<p>I didn’t miss that – I described in the different context of a type alias, similar to what’s available in Swift. Specifically, the key point is that a typealias in other languages is independent and can be used anywhere, not tied to one specific function. It is not a tool to absolve the requirement (or skip the inherent value) of inline types. In my example, the typealias is used to explicitly to describe the function signature, instead of the more disconnected <code>$</code> annotation proposed for elixir.</p>
<aside class="quote no-group" data-username="jswanner" data-post="26" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jswanner/48/24585_2.png" class="avatar"> jswanner:</div>
<blockquote>
<p>having the type signature defined three times is not exactly what I’d call concise</p>
</blockquote>
</aside>
<p>Do you have a proposal of elixir inline types that’s <em>more</em> concise? Because unless you are intolerant of inline types altogether, <code>:: PaymentStatus</code> is quite concise to achieve all of the well know net positives that inline types provide.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367020" 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/a-case-for-inline-type-annotations/71220/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-367020" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367020"
                     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 #26"></div>
  </section>
</div>
    <div class="postbit" id="367043" data-post-id="367043">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="NobbZ" data-post="21" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nobbz/48/27235_2.png" class="avatar"> NobbZ:</div>
<blockquote>
<p>With pattern matching and multi clause function heads, I think having the type annotation in a single fixed location before all of the clauses is the cleaner approach.</p>
</blockquote>
</aside>
<p>I agree that signatures should be out-of-function-head, however I prefer a signature-per-head approach. This is because you lose resolution with a single-signature-for-all-function-heads approach, specifically with different-type-in different-type-out functions (which are a minority, but valid and useful).</p>
<p>That is, the contrived holistic signature here:</p>
<pre data-code-wrap="ex"><code class="lang-ex">$ File.t | URI.t -&gt; binary | Stream.t
def load_resource(resource)

def load_resource(%File{}), do: # return a binary
def load_resource(%URI{}), do: # return a stream
</code></pre>
<p>has strictly less expressive power than a per-clause version that can correlate data-in with data-out when typechecking:</p>
<pre data-code-wrap="ex"><code class="lang-ex">$ File.t -&gt; binary
def load_resource(%File{}), do: # return a binary

$ URI.t -&gt; Stream.t
def load_resource(%URI{}), do: # return a stream
</code></pre>
<p>The exception being if we supported a compound variant that can correlate cause and effect, like</p>
<pre data-code-wrap="ex"><code class="lang-ex">$ (File.t -&gt; binary) | (URI.t -&gt; Stream.t)
def load_resource(resource)

def load_resource(%File{}), do: # return a binary
def load_resource(%URI{}), do: # return a stream
</code></pre>
<p>Personally I prefer per-head over this invented compound form, with the expectation that an IDE or type warning would display the compound form for me when summarizing the possibility space.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367043" 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/a-case-for-inline-type-annotations/71220/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-367043" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367043"
                     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 #27"></div>
  </section>
</div>
    <div class="postbit" id="367044" data-post-id="367044">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="christhekeele" data-post="28" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/christhekeele/48/1039_2.png" class="avatar"> christhekeele:</div>
<blockquote>
<p>The exception being if we supported a compound variant</p>
</blockquote>
</aside>
<p>Afaik that support is meant to exist. It’s at least a case that has been discussed as part of the type theory behind the 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="367044" 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/a-case-for-inline-type-annotations/71220/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-367044" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367044"
                     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 #28"></div>
  </section>
</div>
    <div class="postbit" id="367051" data-post-id="367051">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="smueller" data-post="25" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/48/3857_2.png" class="avatar"> smueller:</div>
<blockquote>
<p>You’re making a case for type aliases, which is not a mutually exclusive concept to inline types. In your example, imagine:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ typealias PaymentStatus = :trial | {:success, metadata} | {:overdue, metadata}
def log_payment_status(:trial :: PaymentStatus) do
def log_payment_status({:success, metadata} :: PaymentStatus) do
def log_payment_status({:overdue, metadata} :: PaymentStatus) do
</code></pre>
<p>Which is the best of both worlds: an explicitly defined function with inline typing, while maintaining a clean and readable signature.</p>
</blockquote>
</aside>
<p>I am not aware of any language that behaves like you propose, where you are annotating <em>part</em> of an alias, instead of annotating the whole value and then exhaustively matching on each part of the alias later on. I found this particularly confusing in the other example you posted:</p>
<aside class="quote no-group" data-username="smueller" data-post="24" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/48/3857_2.png" class="avatar"> smueller:</div>
<blockquote>
<p>Using Rust, Typescript, Kotlin, and Swift for inspiration, this could be:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI | String?) :: String?, do: host
def hostname(url :: URI | String?) when is_binary(url) :: String?, do: hostname(URI.parse(url))
def hostname(nil :: URI | String?) :: String?, do: nil
</code></pre>
</blockquote>
</aside>
<p>It also repeats the signature on every clause - which can become quite verbose - but has the additional confusion arising that some annotations are certainly untrue for that given clause. Take the first clause:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI | String?) :: String?, do: host
</code></pre>
<p>This clause certainly doesn’t deal with with <code>String?</code> but the annotation is there anyway. Not only it is repetitive and confusing, it also means we are incapable of expressing function overloads, where different arguments return different types. What you are proposing is equivalent to saying this Kotlin code</p>
<pre data-code-wrap="kotlin"><code class="lang-kotlin">fun handle(value: String): String = value.uppercase()
fun handle(value: Int): Boolean = value % 2 == 0
fun handle(value: List&lt;Any&gt;): Int = value.size
</code></pre>
<p>should have a repeating type signature, which is clearly not true as seen above, but it would also lead to repeating return types:</p>
<pre data-code-wrap="kotlin"><code class="lang-kotlin">fun handle(value: String | Int | List&lt;Any&gt;): String | Boolean | Int =
</code></pre>
<p>which comes with a massive loss of precision as you no longer capture the information that a “Boolean” is returned only if you gave it an “Int” type.</p>
<p>If your argument is familiarity, all languages I know of that support overloading and inline type signatures have each clause typed independently, instead of repeating the whole signature on every clause. So I objectively find this particular proposal to be more verbose, more foreign, and less powerful than your previous ones. And the issue of clause complexity (mixing pattern matching, default arguments and type signatures in the same construct) is still unaddressed in both.</p>
<hr>
<p>As per my original comment, the way those languages would handle my example would be by rewriting the code as:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def log_payment_status(status :: payment_status()) :: ... do
  case status do
    :trial -&gt; ...
    {:success, metadata} -&gt; ...
    {:overdue, metadata} -&gt; ...
  end
end
</code></pre>
<p>If any of the languages you are using as reference allow partial matching of an existing type alias in the function signature, then I would love to see an example and the accompanying documentation to learn more!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367051" 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/a-case-for-inline-type-annotations/71220/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-367051" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367051"
                     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 #29"></div>
  </section>
</div>
    <div class="postbit" id="367055" data-post-id="367055">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wojtekmach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wojtekmach/120/999_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wojtekmach
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Hex Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>EDIT: José raised similar and more points in the reply above as I was writing this but I’m gonna post the following anyway in case anyone finds this useful.</p>
<aside class="quote no-group" data-username="smueller" data-post="24" data-topic="71220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/smueller/48/3857_2.png" class="avatar"> smueller:</div>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI | String?) :: String?, do: host
def hostname(url :: URI | String?) when is_binary(url) :: String?, do: hostname(URI.parse(url))
def hostname(nil :: URI | String?) :: String?, do: nil
</code></pre>
<p>And now there’s no question of readability, which furthers my point: modern languages have already solved this elegantly and concisely.</p>
</blockquote>
</aside>
<p>Reading this code for the first time, my immediate reaction is:</p>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(%URI{host: host} :: URI | String?) :: String?, do: host
             ^^^^^^^^^^^^^^^^    ^^^ ^^^^^^^^^
</code></pre>
</blockquote>
<p>We’re already pattern matching on a <code>%URI{}</code> so writing <code>URI</code> <em>again</em> feels redundant but writing <code>| String?</code> is confusing, it’s not a nullable string, we’ve already established it’s an URI.</p>
<blockquote>
<pre data-code-wrap="elixir"><code class="lang-elixir">def hostname(url :: URI | String?) when is_binary(url) :: String?, do: hostname(URI.parse(url))
                    ^^^^^       ^  ^^^^^^^^^^^^^^^^^^^
</code></pre>
</blockquote>
<p>This clause has a guard that ensures url is a binary so again, why treat url as possibly a URI or nil?</p>
<p>Reading it again, I suppose the principle is all we have is inline types so we need to repeat them. But, and this may come down to personal preference, to me repeating types over and over again significantly decreases readability.</p>
<p>This repetition could be error prone too, unless the compiler makes sure every clause has matching types. So there’s a potential downside, error proneness, with a potential guard rail, the compiler is smart enough to catch this. So there is nuance and tradeoffs. I was really missing in your initial post discussing nuance and tradeoffs. (This repetition point was just the first thing off the top of my head.) These type annotations don’t exist in the vacuum and need to fit with existing language features like multiple function heads, pattern matching and guards, and default values. Languages you mentioned, TypeScript, Swift, Kotlin, Rust, C#, Python, they have varied support for those features (mostly missing except for default arguments) and neither has all three. So yeah, I’m really curious what are the other tradeoffs of what you’re proposing.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="367055" data-batch-url="/posts/batch_likers">
                        9
                      </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/a-case-for-inline-type-annotations/71220/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-367055" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="367055"
                     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 #30"></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/71220/load_more?page=4">Load more posts (29 remaining)</a>
</div></template></turbo-stream>