In elixir, processes (these are Erlang "processes", not OS processes) are designed to fail when they encounter errors, and the supervising process will restart it according to various rules you can configure. This isn't dissimilar to how kubernetes restarts jobs when they fail, but at a more fine-grained level.
It's actually intended that your function doesn't try too hard to validate it's input types, and just that it will malfunction and crash when it gets something it doesn't know how to handle, because the supervision tree will rescue it and your program can continue, albeit without whatever input caused the malfunction.
This obviously isn't ideal for many types of software, but for complex backend servers and other long-running operations it works really well.
Of course this is not a guarantee to eliminate bugs, but it's a factor that reduces them more than you'd think when coming from a different programming paradigm.
It's actually intended that your function doesn't try too hard to validate it's input types, and just that it will malfunction and crash when it gets something it doesn't know how to handle, because the supervision tree will rescue it and your program can continue, albeit without whatever input caused the malfunction.
This obviously isn't ideal for many types of software, but for complex backend servers and other long-running operations it works really well.
Of course this is not a guarantee to eliminate bugs, but it's a factor that reduces them more than you'd think when coming from a different programming paradigm.