Как использовать правильно введенный путь в некоторой записи

#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/somebase

5. @JustinL. не могли бы вы объяснить, в чем отличие от исходного пути?

Ответ №1:

Если вы определенно хотите использовать Path , вы можете определить каждое поле как

p1 :: Either (Path Rel Dir) (Path Abs Dir) .

Вместо этого я был бы склонен определить свой собственный newtype Dir = Dir String и переместить код, чтобы проверить, какой он, на сайты использования. Или еще быстрее нормализовать пути.