Приходя в Haskell из фона на разных языках OO, одна вещь, которая кажется немного недостатком для меня, заключается в том, что имена функций и полей не привязаны к типам, с которыми они связаны, поэтому их легко запускать в случае, если разные типы данных имеют поля с тем же именем.
Если у меня есть эти три модуля:
module One where
data Foo a = Foo { value :: a }
----
module Two where
data Bar a = Bar { value :: a }
----
module Three where
import One
import Two
foo = Foo { value = 42 } -- compile error here
n = value foo -- and here
неквалифицированные ссылки на value
в модуле Three
считаются неоднозначными, хотя в этом контексте имеет смысл только одно из двух импортированных имен. (В языке OO ссылки на foo.value
и bar.value
будут однозначными.)
Конечно, я могу рассориться, написав Foo { One.value = 42 }
, но это выглядит неудобно. Я также могу назвать поля по-разному, например. "fooValue" и "barValue", но избыточность в Foo { fooValue = 42 }
выглядит неудобно.
Это действительно частный случай более общей проблемы функций в разных модулях, имеющих одно и то же имя, но работающих на разных, несвязанных типах. Я, кажется, сталкивался с ним чаще с именами полей. Например, у меня есть несколько типов данных, не связанных с классом типа, но часто используемых вместе, которые содержат значения цвета, поэтому я хотел бы, чтобы у каждого поля было поле "color".
Как опытные разработчики Haskell называют вещи и организуют их в модули, чтобы избежать такой ситуации?