I think I can provide answers to those questions, based on what I have seen in the ecosystem so far:

> Why put this typeclass in this source file and not that
one?

As you may know, modules can export other modules they depend on, but I would advise to put the typeclass definition in its own .Class module, such as Control.Monad.IO.Class.


> Should I put all my type signatures, typeclasses and data
structures at the top? At the bottom? Should I put them in a separate
source file?

Here is the layout I have seen most used:

module
  ( export1
  , export2
  ) where

imports

data types
instances
type aliases
newtypes
instances

functions (main API)

functions (helpers)

More generally at the project level, make sure you have a tree with few chokepoints. I encourage you to read this article https://www.parsonsmatt.org/2019/11/27/keeping_compilation_fast.html.

Cheers.

PS:

> I can read and reuse my own code 30 years from now and not have to think about how much I hate past me.

This is bound to happen whether or not you have a strong & enforced formatting style. We simply grow up as programmers with time.

Le 12/08/2021 à 00:27, Christopher Conforti a écrit :
On Sun, 8 Aug 2021 08:50:24 +0200
Hécate <hecate@glitchbra.in> wrote:

On my end, I make use of automated style formatters, so that this
kind of thing can be kept consistent during CI. I invite you not to
think too much about the micro-details of code styles, but rather
find a tool that you can configure so that your style can be enforced
automatically. You'll be able to spend more cycles on programme
development.
Indeed, this is the direction I'm heading. However, I'm doing it by
hand first so I can refine my methods to a point I'm satisfied with,
and then build the automation afterwards, hopefully doing it right the
first time. I place value on this because I plan to stick with the same
style throughout all my code so that I can read and reuse my own code 30
years from now and not have to think about how much I hate past me.

The sort of information I'm after answers questions similar to and
including, "Why put this typeclass in this source file and not that
one?" and "Should I put all my type signatures, typeclasses and data
structures at the top? At the bottom? Should I put them in a separate
source file?"

Having outside perspectives from actual people that I'm having
conversations with will help me both learn the finer points of the
topic (from actual programmers) and piece together a strategy I'm happy
with.

On Sun, 8 Aug 2021 08:50:24 +0200
Hécate <hecate@glitchbra.in> wrote:
Note that:

  * Type variables are made explicit, and as such I annotate even the
    simplest of them (with `:: Type`)
  * I align the separators (., => and ->)
  * I use stylish-haskell & hlint
  * If you want finer automated control, try something like Britanny.
Your code is a pleasure to read; I shall enjoy studying it. :-)


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
-- 
Hécate ✨
🐦: @TechnoEmpress
IRC: Hecate
WWW: https://glitchbra.in
RUN: BSD