2

I am currently 'getting my feet wet with monads' (http://learnyouahaskell.com/a-fistful-of-monads#getting-our-feet-wet-with-maybe) and still struggling with part of this concept. I understand the maybe monad mentioned there and can see how to call it, as mentioned here:

ghci> return "WHAT" :: Maybe String  
Just "WHAT"  
ghci> Just 9 >>= \x -> return (x*10)  
Just 90  
ghci> Nothing >>= \x -> return (x*10)  
Nothing  

How do I however call my own monad instance rather than the maybe one if I declare my own instance with its own type, like so:

newtype CustomM a = CustomM {runCustomM:: a -> String}


instance Monad CustomM where
  return a = CustomM (\a -> mempty)
  m >>= f = CustomM (\a -> mempty)


instance Functor CustomM where 
  fmap = liftM 
instance Applicative CustomM where 
  pure = return; (<*>) = ap

using the return will just call the Maybe Monad I suspect. And what about the >>= it would require me to give it a certain type.

NB. I have only made the bind the same way as the return, because I still struggle with understanding what it is supposed to return, and how I can give it a monad m and call the function f on it's value a, when I don't specify the packed type more thoroughly in the left side. But I shall make another post about that.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
Piskator
  • 605
  • 1
  • 9
  • 3
    Not all types can be made into lawful/meaningful monads. Or even functors. `a -> String` surely is not one of them. `String -> a` instead is, it is called (up to some isomorphisms) the "reader monad". `(String, a)` would also be ok (the "writer monad"). It is not an easy task to see if something is or can not be a monad, unfortunately. – chi Sep 15 '22 at 09:01
  • @chi I think the monad definition here is lawful, though not very useful. It's isomorphic to `Proxy`, isn't it? The function being stored is always `mempty`, so you might as well not store it, at which point we have a zero-field type, just like `Proxy`. – amalloy Sep 15 '22 at 16:23
  • 1
    @amalloy `fmap id = id` is broken, I think. Also, `m >>= return = m` is broken for a non-empty-returning `m`. – chi Sep 15 '22 at 16:26
  • 1
    @chi Oh, sure, because the constructor is exported. I was imagining for some reason that the module controlled the constructor, but that's a silly assumption to make because how else are clients going to interact with this thing. – amalloy Sep 15 '22 at 17:12

1 Answers1

6

You can create a value of your CustomM type just like you did with Maybe, using return:

cm = return "WHAT" :: CustomM String

You can also run it, after a fashion:

Prelude Control.Monad> runCustomM cm "foo"
""

Clearly, though, since you've hard-coded it to return mempty, it returns the mempty value for String, which is "".

All that said, though, a -> String is contravariant in a, so it can't be a useful Functor instance. And since it can't be a useful Functor instance, it also can't be a useful Monad instance.

While you can define a degenerate implementation as in the OP, you're not going to have much success making CustomM do anything for real.

Try, instead, swapping the types like e.g. String -> a.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • How do I actually access the Prelude Control.Monad> prompt , from ghci? – Piskator Sep 16 '22 at 13:54
  • 1
    @Piskator you can `import Control.Monad` in GHCi. – Mark Seemann Sep 16 '22 at 14:43
  • I am note sure how to do that. When I write `import Control.Monad CustomM return "what"` in the console I get a parse error. And when I just write `return "what"` after writing `import Control.Monad` I can see that it doesn't change the console into Prelude mode as seen in your example above, nor does it give a specific string `mempty` output or any other output I specify in the monad. – Piskator Sep 21 '22 at 08:39
  • @Piskator Is [the GHCi documentation](https://downloads.haskell.org/~ghc/8.4.2/docs/html/users_guide/ghci.html) of any help? – Mark Seemann Sep 21 '22 at 10:59
  • Not really, I try to do the following: `ghci> import System.IO ghci> import System.IO as IO ghci>` as they suggest, but as you can shee it doesn't change the ghci to the System.IO !? It could be something that is wrong with the way my GHCI is installed perhaps. – Piskator Sep 21 '22 at 11:49
  • @Piskator I don't have enough information to enable me to tell what's wrong, and these comments aren't the best channel for troubleshooting. You may want to consider asking a new question. – Mark Seemann Sep 21 '22 at 14:37
  • Ok, I shall try that htank you Mark – Piskator Sep 21 '22 at 17:57