Parameterising Partial Functions By Error Type - haskell

I have a situation in which the majority of the operations I am using are partial functions. I want the return type of the functions to vary depending on the context, which should determine the kind of exception handling that occurs, and the type of errors that are reported. My current solution is to define a function parameterised by an error type, then implement the operation as an open function using type classes. For example, the following is an implementation of head, assuming a suitable implementation of Error and MonadError for Maybe in terms of the unit type:
class (Error e, MonadError e m) => Head m e | m -> e where
head :: [a] -> m a
errorHead :: (Error e, MonadError e m) => e -> [a] -> m a
errorHead e [] = throwError e
errorHead e (x : xs) = return x
instance Head Maybe () where
head = errorHead ()
instance Head (Either String) String where
head = errorHead "error: empty list"
The advantage of this implementation is that different errors can be thrown depending on the context in which head is called. The question I have is whether this can be accomplished without defining the function using an auxiliary operation and open functions. If not, the second question is whether this solution is optimal. In particular, is there a better way to achieve this behavior?

The http://hackage.haskell.org/package/errors package has many utilities for moving between Maybe, Either, MaybeT, and EitherT.

Related

What is difference between normal functions and typeclass functions?

class (Typeable e, Show e) => Exception e where
toException :: e -> SomeException
fromException :: SomeException -> Maybe e
toException = SomeException
fromException (SomeException e) = cast e
data MyException1 = Exception1A | Exception1B
deriving (Show)
instance Exception MyException1
data MyException2 = Exception2A | Exception2B
deriving (Show)
instance Exception MyException2
It is able to define multiple exceptions. So, multiple fromException functions are able to be defined too. I think it is weird because two functions can have same name and same input.
fromException :: SomeException -> Maybe MyException1
fromException :: SomeException -> Maybe MyException2
Even if the reason why this behavior is ok is "Two functions have different type include return type (and expressions are evaluated based these all types)", it is weird, because I can't define normal functions that way.
f :: Integer -> Maybe Integer
f = cast
f :: Integer -> Maybe Char
f n = cast $ show n
What is difference between normal functions and type class functions?
The fact that you cannot define normal functions that way is the whole difference.
The whole purpose of type classes is to allow overloading - that is, defining multiple different functions with different types, but same name. And have the compiler pick the right one automatically based on types expected in the context.

How can I let Haskell know I don't care what a generic's type is?

I'm working on some code deep in the bowels of an application and would like to make it generic w.r.t. some of the types it's using so I can mock the types for unit tests.
I'm trying to setup a type-class along the lines of:
class (Monad m) => SomeClass m a x d | m -> a where
makeState :: x -> m (a x)
open :: (a x) -> m (a d)
use :: OtherArg -> (a d) -> m ()
close :: (a d) -> m ()
where the m type-variable will be a monad (e.g. IO, ST), a will be some sort of wrapper type in the monad (e.g. MVar, STRef) and x will be known at compile-time, but I don't care about the type of d in the functions using the type-class, just in the type-class instance function implementations themselves.
Right now I'm just trying to get my types setup and it's erroring when I add the constraint to my functions, e.g.:
someFn :: (SomeClass m a Model d) => a d -> a Model -> T m ()
the compiler is complaining that d is ambiguous and won't let me get away without concretely specifying the type, meaning I won't be able to mock it.
I looked briefly at some language extensions and it seems like RankNTypes might be what I need but I'm not sure how to go about utilizing it.
Is this the right approach to accomplish what I'm trying to do, or should I be approaching it differently? (I wouldn't be surprised if I'm approaching it too OOPily as I've been working in Java a lot recently.)
Thanks in advance.
Perhaps it is enough make the fundep mad:
class (Monad m) => SomeClass m a x d | m -> a d where

How to abstract over monads without fighting the type system in Haskell?

I'm currently building a server in haskell and as a newbie to the language, I'd like to try a new approach zu Monad composition. The idea is that we can write library methods like
isGetRequest :: (SupportsRequests m r) => m Bool
isGetRequest = do
method <- liftRequests $ requestMethod
return $ method == GET
class (Monad m, RequestSupport r) => SupportsRequests m r | m -> r where
liftRequests :: r a -> m a
class (Monad r) => RequestSupport r where
requestMethod :: r Method
which work without knowing the underlying monad. Of course in this example, it would have been sufficient to make isGetRequest operate directly on the (RequestSupport r) monad but the idea is that my library might also have more than one constraint on the monad. Yet, I do not want to implement all of those different concerns in the same module nor spread them across different modules (orphan instances!).
That's why the m monad only implements the Supports* classes, delegating the real concerns to other monads.
The above code should work perfectly (with some language extensions to GHC). Unfortunately, I got some problems with the CRUD (Create Read Update Delete) concern:
class (Monad m, CRUDSupport c a) => SupportsCRUD m c a | m a -> c where
liftCRUD :: c x -> m x
class (Monad c) => CRUDSupport c a | c -> a where
list :: c [a] -- List all entities of type a
No I get an error:
Could not deduce (SupportsCRUD m c a0) from the context [...]
The type variable 'a0' is ambiguous [...]
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the class method: liftCRUD [...]
Seems like the type checker doesn't like that the a parameter does not directly arise in the signature of liftCRUD. That's understandable because a cannot be derived from the functional dependencies.
The type checker in my brain tells me that it should not be a problem to infer the type a later on, using AllowAmbiguousTypes, when some method regarding CRUD is executed in a library method. Unfortunately, GHC seems unable to do this inference step, for example
bookAvailable :: (SupportsCRUD m c Book) => m Bool
bookAvailable = do
books <- liftCRUD (list :: c [Book]) -- I use ScopedTypeVariables
case books of
[] -> return False
_ -> return True
yields
Could not deduce (SupportsCRUD m c0 a1) arising from a use of 'liftCRUD' [...]
The type variables c0, a1 are ambiguous [...]
It seems that I am still unable to reason about the compiler. I there a way to resolve this problem? Or at least a way to understand what the compiler is able to infer?
Best Regards,
bloxx
To use ScopedTypeVariables you also need to bind the variables you want to be in scope with forall. So it should be
bookAvailable :: forall m c. (SupportsCRUD m c Book) => m Bool
...
That was all that was necessary (after some trivial fixes I made which I assume were typos from entering your question) for me to get the code to compile.

What does the => sign mean in Haskell?

For some reason I can't find the answer to this anywhere. I tried Googling "Haskell equal sign arrow" and I'm not getting any results. Let's say we have the following function:
sendMessage :: MonadM e m => Message -> m ()
sendMessage message = do
mClient <- getMessageClient
liftIO $ send mClient message
Where exactly are e and m getting used? Are they being passed into the Message object (function?) and then outputted as a single type, m ()?
I don't think it helps that I'm very new to Haskell, but any help is appreciated here.
First off: if you want to know what such and such operator does, don't ask StackOverflow, ask Hoogle!
But in fact Hayoo is no use for => in particular because, unlike almost everything else in Haskell, this is built-in syntax and not an operator that's defined in some library.
Your signature
sendMessage :: MonadM e m => Message -> m ()
means the following: the type of sendMessage is Message -> m (), where m can be any monad that has an instance of the MonadM type class.
That probably doesn't help you much, because in fact MonadM is a rather involved type class. Better consider a simpler example:
sum :: Num n => [n] -> n
This means: the type of sum is [n] -> n, where n can be any number type that's an instance of the Num class, i.e. the class of types supporting subtraction, multiplication, obviously addition etc.. Actually the syntax is shorthand for
sum :: ∀ n . Num n => [n] -> n
meaning that for all types n which fulfill the constraint Num n, the function sum has the signature [n] -> n.
You can instantiate such a polymorphic function with any concrete number type: e.g.
sum :: [Int] -> Int
In your example you'd probably instantiate it to something like
sendMessage :: Message -> MessageT IO ()
The type signature
sendMessage :: MonadM e m => Message -> m ()
can be read
Assuming that the constraint MonadM e m holds, sendMessage has type Message -> m ()
MonadM is (almost certainly) a multi-parameter type class with a functional dependency. Its definition probably looks vaguely like
class Monad m => MonadM e m | m -> e where ....
You don't have to worry about that right now. Writing such classes is a somewhat advanced topic. But it expresses that some operations are available that relate the types e and m, where the type e is determined by the type m.

Converting monads

Lets say I have function
(>>*=) :: (Show e') => Either e' a -> (a -> Either e b) -> Either e b
which is converting errors of different types in clean streamlined functions. I am pretty happy about this.
BUT
Could there possibly be function <*- that would do similar job insted of <- keyword, that it would not look too disturbing?
Well, my answer is really the same as Toxaris' suggestion of a foo :: Either e a -> Either e' a function, but I'll try to motivate it a bit more.
A function like foo is what we call a monad morphism: a natural transformation from one monad into another one. You can informally think of this as a function that sends any action in the source monad (irrespective of result type) to a "sensible" counterpart in the target monad. (The "sensible" bit is where it gets mathy, so I'll skip those details...)
Monad morphisms are a more fundamental concept here than your suggested >>*= function for handling this sort of situation in Haskell. Your >>*= is well-behaved if it's equivalent to the following:
(>>*=) :: Monad m => n a -> (a -> m b) -> m b
na >>*= k = morph na >>= k
where
-- Must be a monad morphism:
morph :: n a -> m a
morph = ...
So it's best to factor your >>*= out into >>= and case-specific monad morphisms. If you read the link from above, and the tutorial for the mmorph library, you'll see examples of generic utility functions that use user-supplied monad morphisms to "edit" monad transformer stacks—for example, use a monad morphism morph :: Error e a -> Error e' a to convert StateT s (ErrorT e IO) a into StateT s (ErrorT e' IO) a.
It is not possible to write a function that you can use instead of the <- in do notation. The reason is that to the left of <-, there is a pattern, but functions take values. But maybe you can write a function
foo :: (Show e') => Either e' a -> Either e a
that converts the error messages and then use it like this:
do x <- foo $ code that creates e1 errors
y <- foo $ code that creates e2 errors
While this is not as good as the <*- you're asking for, it should allow you to use do notation.

Resources