Alat atau metode resolver parameter jenis generik Haskell [duplikat]
Mari kita lihat jenis fungsi ini misalnya:
:t traverse
traverse
:: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
:t id
id :: a -> a
Mereka tidak memiliki jenis beton, tetapi memiliki parameter jenis generik : a
, f
, b
, t
(benar kalau mereka disebut tidak jenis parameter generik menyenangkan)
Jika saya menggabungkan id
dan traverse
menyatu dengan cara ini,
:t traverse id [Just 1, Just 2, Nothing]
traverse id [Just 1, Just 2, Nothing] :: Num b => Maybe [b]
Haskell sekarang dapat mengikat beberapa jenis beton untuk variabel jenis a
, f
, b
, t
.
t = []
a = Maybe bb
f = Maybe
b = Num bb => bb
Di bawah ini saya menyimpulkan jenis dan pemetaan ke parameter dengan tangan, apakah ada cara atau alat di Haskell untuk melakukan ini secara otomatis, sehingga dibutuhkan beberapa bagian yang tersusun ( id
dan traverse
) dalam sebuah contoh, mengekstrak tanda tangan tipe mereka secara umum, dan pada keluaran yang dihasilkan pemetaan dari nama parameter tipe generik ke tipe kesimpulan konkret?
Lihat juga contoh pertama di sini: https://wiki.haskell.org/Type_inferenceuntuk ekspresi " map ord
" tentang cara Haskell menemukan binding dari tipe sebenarnya ke nama.
Jadi ketika kita melihat fungsi secara terpisah kita hanya memiliki nama a
, f
, b
, t
. Tapi kemudian kami menggabungkan fungsi dan memberikan beberapa informasi tambahan seperti [Just 1, Just 2, Nothing]
, dan nama-nama a
, f
, b
, t
dipetakan ke jenis beton.
Saya ingin menangkap dan menampilkan pemetaan ini secara otomatis.
Jawaban
Saya pikir f
dan parameter konstruktor tipet
yang lebih umum , karena mereka bertindak pada tipe untuk memberi Anda tipe (mereka jenis adalah * -> *
, di mana *
berarti "tipe konkret").
traverse id
tidak komposisi, adalah fungsi aplikasi, seperti Anda melewati id
sebagai argumen untuk traverse
. this . that
adalah komposisi fungsi antara this
dan that
, dalam arti matematis, di mana Anda membuat fungsi yang memberikan argumen (pertama) sebagai masukan that
dan memberi makan hasil aplikasi ini ke this
.
Anda mengacu pada contoh di halaman ini , di mana diberikan ini
map :: (a -> b) -> [a] -> [b]
Char.ord :: (Char -> Int)
kompilator dapat menyimpulkan bahwa jenisnya map ord
adalah [Char] -> [Int]
, karena Anda dapat memeriksanya sendiri dengan menulis :t map ord
di baris perintah.
Jika Anda mengharapkan keluaran serupa dengan tipe concerete saat Anda mengetik :t traverse id
, Anda tidak akan mendapatkannya, karena alasan sederhana itu traverse id
masih merupakan fungsi polimorfik, baik dalam argumen tipe konkretnya maupun argumen konstruktor tipe.
Hanya untuk memberikan contoh yang sedikit berbeda, jika Anda mengetik :t traverse (:[])
, where (:[])
has type a -> [a]
, yang merupakan kasus khusus (Applicative f) => a -> f b
yang traverse
diharapkan, Anda mendapatkan output ini,
traverse (:[]) :: Traversable t => t b -> [t b]
yang dibandingkan dengan :t traverse
,
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
memberi tahu Anda bahwa traverse
, dalam traverse (:[])
, telah "dipakai" dengan f === []
dan a === b
.