Reputation: 551
I am new to Haskell, I have read blogs on how Haskell code is very elegant. The way I am writing Haskell code, it does not look elegant at all. Some of the areas I want to improve are
I use case matches on Either values a lot, is using something like fromRight from Data.Either a better option? I also have some code with nested structures, for right values
case eitherResponse of
Right response -> return $ toJSON $ response
Left msg -> Log $ "Error" <> msg
I have a lot of code which looks like this
fname <- URI.mkPathPiece functionname
kch <- URI.mkPathPiece $ T.pack "channel"
vch <- URI.mkPathPiece channel
kca <- URI.mkPathPiece $ T.pack "chaincode"
vca <- URI.mkPathPiece chaincode
let path = Just (True, Data.List.NonEmpty.fromList [fname, kch, vch, kca, vca])
I really do not like the way it looks, how can I improve this?
Also, Haskell for me is very similar to imperative programming in a "do" block. Is that how Haskell code should look or I am on the wrong track here?
Upvotes: 3
Views: 280
Reputation: 60513
You can improve your second example like this:
pieces <- traverse URI.makePathPiece $
NonEmpty.fromList [functionName, "channel", channel, "chaincode", chaincode]
let path = Just (True, pieces)
We omit the T.pack
s by using the {-# OverloadedStrings #-}
extension. Then use traverse
to map a monadic function over a NonEmpty
, which is a traversable container.
I need more context to give a concrete alternative to the first example, but if you have nested structures such as:
case eitherResponse of
Left -> some error ...
Right x ->
case someFunction x of
Left -> some error ...
Right y -> ...
This kind of chaining is exactly what Either
/ExceptT
's Monad
instances do. You can make it look like this:
do x <- eitherResponse
y <- someFunction x
Time to learn about monad transformers!
Upvotes: 3
Reputation: 16214
I just can think in improve a little this part with a subfunction kind of helper function:
toJsonOrError (Right response) = return $ toJSON $ response
toJsonOrError (Left msg) = Log $ "Error" <> msg
Also you can import qualified as @Ri- pointed, to replace Data.List.NonEmpty.fromList like:
import qualified Data.List.NonEmpty as NonEmpty (fromList)
to simplify the line:
Just (True, fromList [fname, kch, vch, kca, vca])
The rest of your code is do
notation and doesn't look like it can be improved (at leas with the code you've shown)
Upvotes: 2