Is there a way to model exception handling in lambda calculus?
I'm asking this because it is very common to see multiple ways in handling exception states in procedural languages and derivative paradigms. Even in C you can emulate this behaviour quite simply using setjmp.h, errno.h and signal.h.
I can imagine in my head a way in the Turing machine state graph a sort of "exception" node that can be reached by any other node, and I guess procedural languages do this sort of thing to implement it.
But in Haskell (my newest obsession) and functional programming in general you don't see all the fuzz about exceptions. I know they exist (Control.Exception?) and I know that functional programming uses monads to model side-effects, but I confess I don't quite understand what it is and how it works.
But i saw in another discussion that all functional languages are kind of syntactic sugar to lambda calculus, so how would such a thing work?
Exception handling in lambda calculus and functional programming
169 Views Asked by Otávio Augusto Silva At
1
There are 1 best solutions below
Related Questions in EXCEPTION
- What should i use Exceptions or Monads for handle if service occur a problem?
- Python Requests: Handling Exceptions and Ensuring Server Response
- What is a better way to allow no user input while also preventing non-number inputs
- New error on random number assigned to local variable , Rails
- spring error exception with oauth2 and securityconfig
- Exception thrown: 'System.InvalidOperationException' in Microsoft.Data.SqlClient.dll
- How to fix this Row nested in Column exception issue in Flutter?
- GDI - Why the printing StartPage() function works in 32 bit but raises an exception in 64 bit?
- Handling Invalid Credential or Login error Exception in Python for Network Devices
- Execution failed for task ':app:compileFlutterBuildDebug'. > Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1Error:
- .NET 6 Custom Nuget package referencing other packages - Do I have to include the other packages myself?
- How to prevent Unity from catching and ignoring ALL exceptions
- My Google Apps Script renames all files in a folder from data in a spreadsheet. Can someone explain why it returns an exception error?
- Python (pylint): Catching general exceptions in validation procedures
- Need a simple example how to catch a data type error en C++
Related Questions in HASKELL
- Typeclass projections as inheritance
- How to generate all possible matrices given a number n in Haskell
- Is there a way to get `cabal` to detect changes to non-Haskell source files?
- How to have fixed options using Option.Applicative in haskell?
- How can I create a thread in Haskell that will restart if it gets killed due to any reason?
- Automatic Jacobian matrix in Haskell
- Haskell writing to named pipe unexpectedly fails with `openFile: does not exist (No such device or address)`
- Why does Enum require to implement toEnum and fromEnum, if that's not enough for types larger than Int?
- Non-exhaustive patterns in function compress
- How to get terms names of GADT in Template Haskell?
- Implementing eval() function with Happy parser generator
- How to count the occurences of every element in a list in Haskell fast?
- In Haskell, what does `Con Int` mean?
- Extract a Maybe from a heterogeneous collection
- Haskell, Stack, importing module shows error "Module not found"
Related Questions in FUNCTIONAL-PROGRAMMING
- On Google Sheets (and only built-in functions allowed, no Google Apps Script) Is it possible to simulate pipe function?
- Why does Enum require to implement toEnum and fromEnum, if that's not enough for types larger than Int?
- Is there a functional way to map a list (N elements) to a list of sums of adjacent elements (N - 1 elements) in Kotlin?
- How to count the occurences of every element in a list in Haskell fast?
- Combine lists with absolute index in functional programming
- How to refactor a loop with iterator. (Returning from closure)
- In Haskell, what does `Con Int` mean?
- Setting up different Java class fields value by a single value on some counter value
- Why doesn't map read show (Integer) work to separate each value in a string of Integers?
- Grouping by multiple fields and counting using in Java 8
- Variable capture: How variables behave in function closures
- Composing React Providers with Value props in Typescript
- How can atomicModifyIORef cause leaks? And why does atomicModifyIORef' solve the problem?
- How can I change XMobar's Kbd monitor plugin such that clicking on it loops throught the layouts?
- How to get success or error data without folding the response while using fpdart in flutter?
Related Questions in THEORY
- Theory of Comp Sci - State Diagrams NFAs
- About Suffix Trees features
- Cryptography Notion - Diffie-Hellmann
- Correct labeling for this regular language?
- How to measure distinct time intervals - data generation, insertion, and database processing latency - in PostgreSQL
- Looking for strategies to check if a system has been restarted
- Difference between similar terms in OS and GPU
- best approch for filtering
- How to Estimate Theoretical Execution Time for Dynamic Data Generation in PostgreSQL Function?
- Reduce if/else-if on a bunch of partially overlapping conditions
- Theory of algorithms and counting the number of operations
- Nodejs readable-stream vs array.map
- Use a YOLO neural network to extend dataset for re-train same model?
- Effective ways to avoid skipping a record
- Why is array element referencing a constant time operation?
Related Questions in LAMBDA-CALCULUS
- How could this Y' same as this Y combinator itself?
- Type information system recovery
- mock - church numerals?
- beta-equivalence, beta-reduction and transitive+reflexive beta-reduction
- Overlapping Days Calculation Nightmare
- Lambda Calculus - Evaluating Custom Rewrite Rules to Increment
- Is it possible, using PHOAS, to evaluate a term to normal form, and then stringify it?
- Are numbers also functions in functional programming?
- Valid Lambda Expressions
- 'Segmentation Fault' occurred when Lambda Function in Python recurves over 1e5 times
- Why Rust fails when I try to implement recursion with "S I I" from SKI-calculus?
- Do you multiply or add when simplifying λ-expressions?
- How does "true" evaluate in the lazy lambda calculus?
- What is (Y Y), the Y-combinator applied to itself?
- How to prove Theorem euclid_gcd : forall a b z, euclid a b z -> gcd a b z. using coq?
Trending Questions
- UIImageView Frame Doesn't Reflect Constraints
- Is it possible to use adb commands to click on a view by finding its ID?
- How to create a new web character symbol recognizable by html/javascript?
- Why isn't my CSS3 animation smooth in Google Chrome (but very smooth on other browsers)?
- Heap Gives Page Fault
- Connect ffmpeg to Visual Studio 2008
- Both Object- and ValueAnimator jumps when Duration is set above API LvL 24
- How to avoid default initialization of objects in std::vector?
- second argument of the command line arguments in a format other than char** argv or char* argv[]
- How to improve efficiency of algorithm which generates next lexicographic permutation?
- Navigating to the another actvity app getting crash in android
- How to read the particular message format in android and store in sqlite database?
- Resetting inventory status after order is cancelled
- Efficiently compute powers of X in SSE/AVX
- Insert into an external database using ajax and php : POST 500 (Internal Server Error)
Popular # Hahtags
Popular Questions
- How do I undo the most recent local commits in Git?
- How can I remove a specific item from an array in JavaScript?
- How do I delete a Git branch locally and remotely?
- Find all files containing a specific text (string) on Linux?
- How do I revert a Git repository to a previous commit?
- How do I create an HTML button that acts like a link?
- How do I check out a remote Git branch?
- How do I force "git pull" to overwrite local files?
- How do I list all files of a directory?
- How to check whether a string contains a substring in JavaScript?
- How do I redirect to another webpage?
- How can I iterate over rows in a Pandas DataFrame?
- How do I convert a String to an int in Java?
- Does Python have a string 'contains' substring method?
- How do I check if a string contains a specific word?
First note: If you're starting out in Haskell, stay away from
Control.Exception. That module emulates traditional Java-style exception handling inside theIOmonad. It's a good thing to learn about eventually, but it's not the conventional way of dealing with (controllable) errors within purely-functional Haskell code.As you've already noted, the usual way to handle exceptional situations in a functional language like Haskell is with monads. So let's talk about monads, but instead of talking in the abstract, let's talk about one specific one. This type exists in the standard library, but I'm calling it by another, more evocative name.
The way we're going to use this type is simple. Anytime we have a function that could "throw" an exception, that function returns a
Result e a, whereais the result type if everything goes well andeis the type of exception we throw. It's sort of like checked exceptions in Java but on a much more granular scale.As a perhaps stereotypical example, consider a function which divides two numbers but errs out in
Resultif we attempt to divide by zero. Its signature would be something like this.So if we ever find ourselves in a situation where we have a
Result e a, that's a value of typea, with the major caveat that we might have already failed and theResultobject "contains" an exception of typee.Now let's see what operations a
Monadinstance would give us. The hierarchy for monads starts atFunctor, then moves down toApplicative, then finallyMonad.Functorgives usWe can read this as "If I have a way to go from
atob(that cannot fail), then I can always take a (potentially-failed)aand produce a (potentially-failed)b". This makes sense, and we can write it easily.We simply preserve the error state. If the computation already erred, we keep the error. If not, we apply our (perfectly safe, pure) function
f.Now a natural question arises: What if I have a function of two arguments
f :: a -> b -> c, but I havex :: Result e aandy :: Result e b? We can try to curry the function, but once we apply our first argument, we have a problem.Now I want to apply a function which might have failed to a value which might have failed. Put another way, I have two potentially-error objects and I want to combine them (in this case, using function application). That's where
Applicativecomes in.The
Applicativeoperator(<*>)is justfmapwith a function that's already inside of our applicative (in this case, a function that might secretly be an exception).Here's how it's implemented.
Now we can apply our example function as
Additionally,
Applicativegives uspure :: a -> Result e awhich is just implemented aspure = Okfor our type. This allows us to treat a pure value as a potentially-failing value, essentially "forgetting" the fact that it can't fail. It comes in handy when you're trying to make type signatures line up, such as if you have a function that's expecting a potentially-failing computation but all you have is a pure one.Finally, we get to
Monad.Monadonly requires one function to be implemented, and that's the bind operator(>>=).Okay, that looks pretty different. Let's flip the arguments.
We've just moved the
Resultpart of the function over a bit. Now, not only can our function have failed, but our function can choose whether or not it fails based on the inputavalue from earlier in our computation.This is amazingly powerful, because it allows us to implement the most common thing we do with exceptions in an imperative language: propagate them.
First, let's see how it's implemented.
Now, anytime we call a function and want to simply let the exception propagate to our own caller, we use
>>=on the result of the function.In Java, we would write this as
It sure would be nice if we could write our Haskell code in a neat way like this that lets us almost forget we're dealing with effects at all. Let me indent this a little differently and remove some unnecessary parentheses.
Introduce
donotation. It's very important to keep in mind thatdonotation is pure syntax sugar. At no point does it add anything new to the language. It's implemented entirely in terms of(>>=)and the otherMonadoperations. This is exactly equivalent to the above.So it's all implemented in terms of functions. Rather than "applying" a function, we use this funny sort of function-application-like operator called "bind" and written
(>>=). As the old saying goes, it's functions all the way down.It's worth noting that this is exactly what Rust does as well. Rust takes a monadic approach to error handling with its own
Result<T, E>type.fmapis.map,pureisOk, and(>>=)is.and_then. (There's no direct equivalent to(<*>), but it can be implemented in terms of.and_theneasily) And the?operator in Rust, which basically means "propagate errors to my caller", is really just a shortcut to short-circuit out if you have an error. It's Rust's answer to Haskell'sdonotation.