3

I was hoping to get some helpful input on understanding Monad Transformers, and in relation to that, what happens using do notation. The example I am trying to understand is the following:

data ProtectedData a = ProtectedData String a
accessData :: String -> ProtectedData a -> Maybe a
accessData s (ProtectedData pass v) =
 if s == pass then Just v else Nothing
type Protected s a = MaybeT (Reader (ProtectedData s)) a
-- untangles the monad construction
run :: ProtectedData s -> Protected s a -> Maybe a
run ps psa = runReader (runMaybeT psa) ps
access :: String -> Protected a a
access pass = do
 -- ask :: ReaderT (ProtectedData a) Identity (ProtectedData a) 
 -- lift :: ... -> MaybeT (ReaderT (ProtectedData a) Identity) (ProtectedData a) 
 pd <- lift ask
 -- as i understand it: ask returns the value inside the thing.
 -- the left arrow actually applies the monad
 let v = accessData pass pd
 -- return :: Maybe a -> Reader (ProtectedData a) (Maybe a)
 MaybeT $ return v

As I understand it the Protected type describes some protected data, that is stored in a shared environment (Reader) and is of type Maybe (MaybeT).

I am having problems with the type-variables s and a:

  • Does s describe the string (password) of the protected data, and a the type of the protected data?
  • Does s describe the type of the protected data, and if so, what does a describe?

In the function run:

run :: ProtectedData s -> Protected s a -> Maybe a
run ps psa = runReader (runMaybeT psa) ps

As I understand it, the Reader from inside Protected is run on the ProtectedData, to return the value.

This leaves only the function access:

access :: String -> Protected a a
access pass = do 
 pd <- lift ask
 let v = accessData pass pd
 MaybeT $ return v

Which is the one providing the most headache for me. First I am having issues grasping the effect and result.

  • Is this function used to inject passwords and data into the Reader?
  • Is it used to access data and fail if the wrong password is given?

Secondly I am having trouble understanding the first line

pd <- lift ask
  • I understand, that ask is used to get access to the shared environment through the Reader, but why do I have to lift it to a MaybeT to get the actual value inside of it?
Micha Wiedenmann
21.1k22 gold badges96 silver badges142 bronze badges
asked Sep 5, 2021 at 13:21

1 Answer 1

6

As i understand it the Protected type describes some "protected" Data

No. Protected s a should be seen as the type of a program that returns a value of type a. During the computation the program has read-only access to a secret value of type s, and only if it "knows" the proper password.

Such secret value, paired with its password, has type ProtectedData s.

does s describe the type of the protected Data, and if so, what does a describe?

Yes. Here a is the, generic, type of the result of the program.

An an example, you can consider the case where the password is a String (it has to be, in your code the string type is hard-coded) and the secret value has type s = Int. Then you write a program which accesses the secret integer, and checks whether it's positive, returning a Bool. Here, a = Bool.

Note that I simplified the scenario a bit. Since we also use MaybeT, we are modelling a program that does not always return a value of type a, but that can also fail. A possible failure could be caused by using the wrong password. In such case, MaybeT roughly aborts the program in the middle of its execution.

The signature

access :: String -> Protected a a

is perhaps better understood if we write it as

access :: String -> Protected s s

showing that it is a helper function to access the secret value (or failing), given a password attempt. It is used as follows:

myProg :: Protected Int Bool
myProg = do
 v <- access "123456" -- try accessing the protected int
 return (v > 0)

If the password is wrong, the above code will cause a failure (run will return Nothing)

> run (ProtectedData "actual password" 42) myProg
Nothing

If the password is correct, instead it will produce the right boolean:

> run (ProtectedData "123456" 42) myProg
Just True

Here Just means that the password was correct, and True indicates that the protected Int was positive.

answered Sep 5, 2021 at 14:01
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, realizing to think of Protected s a as a Program with return type a accessing protected Data of type s really helped me understand the concept. If i understand correctly this means i can even use other Monads in my Program: giveEven :: String -> Protected [Int] [Int] giveEven s = do v <- access s return (filter even v)
@Superschnitzel Your code is correct, but you are not really using [] as a monad there. You could, though, but it would be "orthogonal", so to speak. s can be any type, and that includes monadic ones, but those do not interfere with the main monad Protected s.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.