Bind-like operator for dogs

I’m in search of operators that I can use like >>= to keep the chain of operators “flowing” without the need of additional Justs (line 17 and 18).

module Main where

import Control.Monad (mfilter)

main :: IO ()
main =
  print $
    create "Jim"
      >>= train 1
      >>= train 4
      >>= train 1
      >>= train 4
      >>= train 2
      >>= train 2
      >>= Just . rename "Lilly"
      >>= mfilter (not . isToClever) . Just
      >>= train 4
      >>= train 2

data Dog = Dog String Int deriving (Show)

create :: String -> Maybe Dog
create name =
  if null name
    then Nothing
    else Just $ Dog name 0

train :: Int -> Dog -> Maybe Dog
train hours (Dog name level) =
  let newLevel
        | hours > 6 = Nothing
        | hours == 0 = Just level
        | hours < 3 = Just (level + 2)
        | otherwise = Just $ level + hours
   in Dog name <$> newLevel

rename :: String -> Dog -> Dog
rename newName (Dog _ level) =
  Dog newName level

isToClever :: Dog -> Bool
isToClever (Dog _ level) =
  level > 100


so the code looks like this:

      >>= train 2
      >>= train 2
      ??? rename "Lilly"
      ??? mfilter (not . isToClever)
      >>= train 4

Notes: I tried to find a type on hoogle, but didn’t find one that chains as nice as >>=. A simple <$> works for the rename "Lilly" case, but then the flow is broken.

I’m not sure if it works with operator-precedence but this should be <&>

1 Like

No need for fancy operators. Just state your intention as it is: pure . rename. Or make rename into the same shape as the train.