Berikut skenario: Saya sudah menulis beberapa kode dengan tipe tanda tangan dan GHC mengeluh tidak dapat menyimpulkan x ~ y untuk beberapa x
dan y
. Anda biasanya dapat melempar GHC ke tulang dan menambahkan isomorfisme ke batasan fungsi, tetapi ini adalah ide yang buruk karena beberapa alasan:
- Itu tidak menekankan pemahaman kode.
- Anda dapat berakhir dengan 5 kendala di mana seseorang akan mencukupi (misalnya, jika 5 tersirat oleh satu kendala lebih spesifik)
- Anda dapat berakhir dengan batasan palsu jika Anda melakukan kesalahan atau jika GHC tidak membantu
Saya hanya menghabiskan beberapa jam berjuang melawan 3. Saya bermain dengan syntactic-2.0
, dan saya mencoba untuk mendefinisikan versi domain-independen share
, mirip dengan versi yang didefinisikan dalam NanoFeldspar.hs
.
Saya punya ini:
{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic
-- Based on NanoFeldspar.hs
data Let a where
Let :: Let (a :-> (a -> b) :-> Full b)
share :: (Let :<: sup,
Domain a ~ sup,
Domain b ~ sup,
SyntacticN (a -> (a -> b) -> b) fi)
=> a -> (a -> b) -> a
share = sugarSym Let
dan GHC could not deduce (Internal a) ~ (Internal b)
, yang jelas bukan tujuan saya. Jadi entah saya telah menulis beberapa kode saya tidak bermaksud (yang memerlukan kendala), atau GHC ingin kendala itu karena beberapa kendala lain yang saya tulis.
Ternyata saya perlu menambahkan (Syntactic a, Syntactic b, Syntactic (a->b))
ke daftar kendala, tidak ada yang menyiratkan (Internal a) ~ (Internal b)
. Saya pada dasarnya menemukan kendala yang benar; Saya masih belum memiliki cara sistematis untuk menemukannya.
Pertanyaan saya adalah:
- Mengapa GHC mengusulkan batasan itu? Tidak ada tempat dalam sintaksis yang memiliki kendala
Internal a ~ Internal b
, jadi dari mana GHC menariknya? - Secara umum, teknik apa yang dapat digunakan untuk melacak asal-usul kendala yang menurut GHC dibutuhkan? Bahkan untuk kendala yang dapat saya temukan sendiri, pendekatan saya pada dasarnya kasar memaksa jalur menyinggung dengan secara fisik menuliskan kendala rekursif. Pendekatan ini pada dasarnya menuruni lubang kelinci tanpa batas dan merupakan metode paling efisien yang dapat saya bayangkan.
a
dan b
terikat - lihat tipe tanda tangan di luar konteks Anda - a -> (a -> b) -> a
, tidak a -> (a -> b) -> b
. Mungkin itu saja? Dengan pemecah kendala, mereka dapat mempengaruhi kesetaraan transitif di mana saja , tetapi kesalahan biasanya menunjukkan lokasi "dekat" ke tempat kendala itu diinduksi. Itu akan keren meskipun @jozefg - mungkin memberi batasan pada tag atau sesuatu, untuk menunjukkan dari mana asalnya? : s