Używam Wyrafinowany dla typów wyrafinowania w Haskell ostatnio i napotkał poważne problemy z użytecznością . Nie mogę zrozumieć, jak udoskonalić całą listę wartości w czasie kompilacji.

Na przykład mogę pisać:

{-# LANGUAGE TemplateHaskell #-}

import Refined

oneToThree :: [Refined Positive Int]
oneToThree = [$$(refineTH 1), $$(refineTH 2), $$(refineTH 3)]

Ale nie mogę tego zrobić, wyklucza zdolność stosowania składni zasięgu, ponieważ Refined nie ma (dla dobrego powodu) mieć instancję dla Enum.

Chciałbym móc zrobić coś takiego

oneToThree :: [Refined Positive Int]
oneToThree = $$(traverse refineTH [1..3])

Ale nie mogę tego zrozumieć, ponieważ nie mogę podnieść [TExp (Refined Positive Int)] do TExp [Refined Positive Int].

Czy jest szablon Haskell Magic, którego brakuje, co pozwoli mi to zrobić?

Byłoby również otwarte na sugestie dotyczące lepszych bibliotek typu wyrafinowania, jeśli ktoś ma sugestię.

3
Devin Lehmacher 11 marzec 2020, 02:54

1 odpowiedź

Najlepsza odpowiedź
sequenceQTExpList :: [Q (TExp a)] -> Q (TExp [a])
sequenceQTExpList [] = [|| [] ||]
sequenceQTExpList (x:xs) = [|| $$(x) : $$(sequenceQTExpList xs) ||]

Następnie użyj go jako

$$(sequenceQTExpList $ map refineTH [1..3])

Masz rację, że czuje się jak traverse. Typ jest jednak nieco wyłączony, z dodatkowym Q unosi się wokół. Nie widzę niczego przebierającego, który pozwala połączyć te warstwy.

Niestety, dużo stosowanego mechanizmu jest składni, a nie funkcje. Tam nie jest oczywistym sposobem, aby zrobić zarówno podnoszenie, jak i splicing jako funkcje, więc utknąłeś pisanie pomocy na zamówienie dla każdego typu kontenera, zamiast do użycia Traversable. To ciekawy problem. Jeśli istnieje czyste rozwiązanie, miałoby to mieć duże szanse na dotarcie do przyszłej wersji szablonu Haskell, jeśli został wychowany do opiekunów. Ale po prostu nie widzę tego teraz.

3
Carl 11 marzec 2020, 02:01