#haskell #path
#haskell #путь
Вопрос:
У меня есть некоторая запись, где должно быть несколько путей / файлов. Давайте предположим, что я хочу использовать для них тип Path, и они могут быть относительными и абсолютными одновременно. Я могу сделать:
data SomeRecord = SomeRecord {
p1 :: forall a. Path a Dir
,p2 :: forall a. Path a Dir
, ...
}
но как назначить некоторые конкретные Path
значения для p1, p2, pN, когда я получу сообщение об ошибке жесткого типа. Также мне нужно будет добавить различные ограничения к этим объявлениям p1, p2 (например, Show …). Другой способ:
data SomeRecord a b c d e ... z = SomeRecord {
p1 :: Path a Dir
,p2 :: Path b Dir
...
,p26 :: Path z Dir
}
который:
- извлекает все параметры типа в
SomeRecord
- использование нескольких
SomeRecord
в одном списке сейчас невозможно, поэтому мне нужно снова добавитьforall
предложения для таких списков и поиграть с ограничениями
Каков канонический способ сделать это? Чтобы избежать хорошо типизированного Path
в таком контексте? Если это так, означает ли это, что такие типы (например Path
) не подходят для нескольких полей в записях?
Комментарии:
1. Суть
path
в том, что вам важно, является ли путь относительным или абсолютным. Если вы этого не делаете, то не используйте его (хотя большую часть времени вам, вероятно, все равно, я действительно не могу вспомнить много сценариев, где вы действительно хотите сочетание относительных и абсолютных путей)2. Вариант использования таков: я извлекаю из некоторой базы данных путь, который является Dir, но он может быть относительным или абсолютным. Итак, если мне нужен более специальный тип, чем FilePath / Text, мне нужна некоторая информация о том, что это каталог, а не файл, поэтому я вспомнил, что это
Path
хранит такую информацию (Dir
/File
), чтобы отличать файлы от каталогов. Но там нет типаPath {Dir|File}
. И если мне это нужно, я получаю этот бесполезный параметр3. Может быть, это даже теоретический вопрос: если у вас фантомный тип
T a b c d e
и вам нужен какой-то подтип, подобныйT a b e
, в некоторой записи с большим количеством таких полей, какое наиболее хорошее решение (чтобы избежать шаблонного кода и подобных проблем)?4. Обратите внимание, что у меня есть ответвление пути, с
SomeBase
которым выполняется то, что вы ищете, mstksg.github.io/path/Path-Posix.html#t:SomeBase . По сути, это ответ @bergey. Форк здесь github.com/mstksg/path/tree/somebase5. @JustinL. не могли бы вы объяснить, в чем отличие от исходного пути?
Ответ №1:
Если вы определенно хотите использовать Path
, вы можете определить каждое поле как
p1 :: Either (Path Rel Dir) (Path Abs Dir)
.
Вместо этого я был бы склонен определить свой собственный newtype Dir = Dir String
и переместить код, чтобы проверить, какой он, на сайты использования. Или еще быстрее нормализовать пути.