Имя сталкивается между полевыми маркировками различных типов данных в Haskell

Прибывая к 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 } выглядит неловким также.

Это - действительно особый случай более общего вопроса функций в различных модулях, которые имеют то же имя, но воздействуют на различные, несвязанные типы. Я, кажется, сталкиваюсь с ним чаще с именами полей, все же. Например, у меня есть несколько типов данных, не связанных классом типа, но часто используемых вместе, которые содержат значения цвета, таким образом, я хотел бы, чтобы у каждого было поле, названное "цветом".

Как опытные разработчики Haskell называют вещи и организуют их в модули, для предотвращения этого типа ситуации?

15
задан Don Stewart 20 April 2011 в 22:48
поделиться

3 ответа

Расширение GHC -XDisambiguateRecordFields разрешит foo = Foo {value = 42} (но не n = value foo ).

Существует большой объем литературы о недостатках текущей системы записи Haskell и кандидатах на ее замену, а также о нескольких библиотеках, которые сейчас пытаются предоставить более хорошие решения. fclabels - единственный, который я использовал лично.

Этот вопрос StackOverflow похож, и некоторые ответы на него также могут быть вам полезны.

Это действительно частный случай более общий вопрос функций в разные модули, у которых одинаковые имя, но действовать по другому, несвязанные типы.

Для решения этой проблемы обычно достаточно квалифицированного импорта и псевдонимов.

9
ответ дан 1 December 2019 в 04:33
поделиться

Вы можете рассмотреть класс типов, если есть общая функция доступа для всех этих типов. Например,

class Fieldable a where
     field :: a -> b

instance Fieldable (a,b) where
     field = fst

И т.д.

1
ответ дан 1 December 2019 в 04:33
поделиться

Как опытные разработчики Haskell называют вещи и организуют их в модули, чтобы избежать подобных ситуаций?

Я работал только с несколькими опытными разработчиками Haskell, и они ужасно такие вещи, как

data Foo a = Foo { foo_value :: a }

data Bar a = Bar { bar_value :: a }

или даже

data Apocalypse a = A { ap_value :: a }

В общем, у меня такое чувство, что многие старые хаскелеры не любят полные имена и действительно хотят притвориться, что в мире есть только одно большое пространство имен, прямо из Темные времена. (Было время, когда компиляторы C имели такие же ограничения на имена полей, поэтому режим в struct stat называется st_mode , а не просто режим ].)

Вы можете перегрузить имена классами типов, но опытные разработчики, которых я знаю, не любят ненужные классы типов. Я никогда не могу понять, когда они думают, что типовой класс будет бесплатным или нет.

Я надеюсь, что однажды люди, работающие с Haskell, придут к соглашению с иерархическим пространством имен и начнут использовать уточненные имена. Как задумал Бог.

4
ответ дан 1 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: