Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using long where statements bad coding style?

I am a Haskell newbie, so I don't know a lot about the coding style. I have a function that chains a lot of random generators. Is this kind of code considered in bad style, wherein I have ~10 lines after a where statement? If so, what are the alternatives?

#!/usr/bin/env runhaskell
{-# LANGUAGE UnicodeSyntax #-}
module Main where

makeDummy :: RandomGen g ⇒ [String] → FilePath → g → (FilePath, g)
makeDummy words root gen0 = (fullPath, gen7)
  where
      (numWordsInTitle, gen1) = randomR (1 :: Int, 4 :: Int) gen0 -- unused
      (title, gen2) = randomChoice words gen1
      (year, gen3) = randomR (1800 :: Int, 2100 :: Int) gen2
      (resNum, gen4) = randomChoice ["1080", "720", "480"] gen3
      (resLetter, gen5) = randomChoice ["P", "p", "i", "I"] gen4
      res = resNum ++ resLetter
      (shuffled, gen6) = shuffle [title, show year, resNum ++ resLetter] gen5
      (fileExt, gen7) = randomChoice [".mkv", ".mp4", ".ogv", ".srt", ""] gen6
      path = (++ fileExt) $ intercalate " " shuffled
      fullPath = root </> path

As this could be a somewhat subjective subject, please restrain answers to relfect the Haskell community code style norms, rather than personal opinion/aesthetics.

I am aware of the possibility of using getStdRandom, but would like to use a pure function here, preferrably.

like image 686
Langston Avatar asked Jul 18 '15 20:07

Langston


People also ask

Is it bad to have long lines code?

In addition to negatively affecting readability, having very long lines can destroy the positive impact of code indentation, which makes the code even harder to understand and maintain (because of chaotic line returns).

Are long if-else statements Bad?

Similarly, there aren't any bad practices when using if-else or else-if conditions. Of course, using else statements should be done carefully, as it's difficult to predict the scope of it. If any condition besides the if clause goes into else , that might not be what you actually want.

Why might it matter if code is long or short?

Arguably, using shorter lines of code is more efficient than spreading the code over several lines. If you have more lines of code, there are more places for bugs to hide and finding them might be more of a hassle. Fewer lines of code can achieve the same results (and probably better) than many lines of code.


2 Answers

By request, here's how to rewrite the function using State in the most direct way. Note that the top level type signature hasn't changed.

makeDummy :: RandomGen g ⇒ [String] → FilePath → g → (FilePath, g)
makeDummy words root = runState $ do
    numWordsInTitle <- state $ randomR (1 :: Int, 4 :: Int) -- unused
    title <- state $ randomChoice words
    year <- state $ randomR (1800 :: Int, 2100 :: Int)
    resNum <- state $ randomChoice ["1080", "720", "480"]
    resLetter <- state $ randomChoice ["P", "p", "i", "I"]
    let res = resNum ++ resLetter
    shuffled <- state $ shuffle [title, show year, resNum ++ resLetter]
    fileExt <- state $ randomChoice [".mkv", ".mp4", ".ogv", ".srt", ""]
    let path = (++ fileExt) $ intercalate " " shuffled
    let fullPath = root </> path
    return fullPath

More usually, you would avoid most of the uses of state $ by defining the utility functions such as randomChoice to already be in the State monad. (This is more or less part of what the MonadRandom package does.)

like image 151
Ørjan Johansen Avatar answered Oct 22 '22 14:10

Ørjan Johansen


Yup! This is the sort of situation where a state monad (or even, more specifically, a randomness monad) is really handy. These let you chain together computations that all transform some sort of state, in this case the random seed. See, for example, Control.Monad.State or look for MonadRandom.

like image 30
dfeuer Avatar answered Oct 22 '22 14:10

dfeuer