Eu suspeito que isso depende da linguagem. Quanto à programação funcional, eu me envolvi principalmente com Haskell, então vou explicar como funciona lá.
O código Haskell é organizado em "módulos", que são basicamente apenas coleções de funções e tipos de dados. Cada módulo é um único arquivo. Um módulo é uma espécie de mistura entre uma classe Java e um pacote Java - o escopo exato do que um módulo faz varia. Um módulo também tem controle sobre quais funções e tipos de construtores serão exportados e quais serão ocultados; isso é semelhante a privatee publicem Java.
Nos meus próprios programas, gosto de fazer com que os módulos façam uma coisa, semanticamente; isso os torna como uma classe Java, exceto que eles podem definir vários tipos de dados. Os módulos que eu uso da biblioteca padrão, como Data.List, são mais como pacotes - eles fornecem um conjunto de funções utilitárias semelhantes. Isso também é muito semelhante a classes Java estáticas como java.util.Arrays.
Os módulos também são como pacotes Java, pois podem ser aninhados para maior clareza (acho que isso não afeta o código). Em geral, para um único projeto, dou um nome (digamos Project) e todos os meus módulos fazem parte disso (por exemplo, Project.Parsee Project.Run). Se eu estivesse escrevendo um código mais parecido com uma biblioteca do que com um aplicativo, eu o organizaria com base no que estava fazendo, como Data.Listou Control.Monad. Uma grande diferença em relação a outros idiomas é que Haskell incentiva a limitação de E / S e a colocação de tudo em um só lugar. Um grande número de módulos não possui E / S e, para qualquer projeto, eu gosto de ter o máximo de módulos possível.
Como exemplo, estou trabalhando em uma linguagem de programação simples que estou chamando de TPL (sem uma boa razão). Para isso, criei dois módulos simples: o TPL.Parseque define a representação interna da linguagem e como analisá-la, e o TPL.Runque executa o intérprete e lida com variáveis e IO. Para compilar e executar o código, geralmente existe um Mainmódulo que acaba sendo o ponto de entrada do programa.
Existe uma liberdade significativa na organização das funções em um arquivo; é exatamente isso que eu gosto de fazer. Eu defino meus tipos de dados no topo, antes de serem usados em outros lugares. Logo após definir os tipos de dados, implemento o que for necessário para torná-los parte de suas classes de tipos apropriadas - é como implementar uma interface. Então eu sigo com lógica e várias funções auxiliares, conforme apropriado. Finalmente, eu gosto de ter todas as minhas funções de IO na parte inferior, terminando com main. Isso deixa claro exatamente o que está fazendo qualquer IO e onde o programa é iniciado.
Portanto, em resumo: as funções estão contidas em módulos, cada um dos quais composto por um único arquivo. Vários módulos podem compor um programa ou biblioteca; o primeiro geralmente inclui um Mainmódulo que é seu ponto de entrada. Dentro de um arquivo, existem opções diferentes para organização, mas eu prefiro agrupar tipos de dados na parte superior, E / S na parte inferior e lógica no meio.
What's stopping you from...Anos e anos de programação com uma mentalidade completamente diferente, a ponto de o código Haskell não computar mentalmente. E, claro, você está assumindo que os projetos reais são sempre corretamente e bem organizado (talvez eles são, mas como é um noob como eu para saber?)