Pertanyaan dipromosikan tipe data dan contoh kelas


Tipe data yang dipromosikan memiliki jumlah tipe tetap yang merupakan anggota dari jenis data yang dipromosikan. Di dunia yang tertutup ini, apakah masuk akal untuk mendukung pemanggilan fungsi pada sebuah typeclass tanpa kamus secara eksplisit dalam lingkup?

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}

data DataType = Constructor

data DataTypeProxy (e :: DataType) = DataTypeProxy

class Class (e :: DataType) where
  classFunction :: DataTypeProxy e -> IO ()

-- this is the only instance that can be created
instance Class 'Constructor where
  classFunction _ = return ()

-- adding the Class constraint fixes the build break
-- disp :: Class e => DataTypeProxy e -> IO ()
disp :: DataTypeProxy e -> IO ()
disp = classFunction

main :: IO ()
main = disp (DataTypeProxy :: DataTypeProxy 'Constructor)

Contoh yang dibuat ini tidak berfungsi di kepala GHC. Ini tidak mengherankan tetapi tampaknya bahwa DataKind ekstensi mungkin membuat ini menjadi mungkin.

test.hs:18:8:
    No instance for (Class e) arising from a use of `classFunction'
    Possible fix:
      add (Class e) to the context of
        the type signature for disp :: DataTypeProxy e -> IO ()
    In the expression: classFunction
    In an equation for `disp': disp = classFunction

4
2018-06-12 20:23


asal


Jawaban:


Tidak. Melakukan hal itu berarti bahwa tipe data hantu perlu "ditandai" dengan informasi jenis tambahan pada waktu proses, dan akan menghasilkan ambiguitas.

data DataType = Constructor | SomethingElse

data DataTypeProxy (e :: DataType) = DataTypeProxy 
...
instance Class 'SomethingElse where
   classFunction _ = putStrLn "hello world"

instance Class 'Constructor where
   classFunction _ = return ()

disp :: DataTypeProxy e -> IO ()
disp = classFunction

main = disp DataTypeProxy

apa yang harus dilakukan program ini? Haruskah tidak dikompilasi? Jika tidak, maka dengan menambahkan konstruktor untuk tipe, kami mengambil program yang Anda ingin mengkompilasi, dan menghasilkan satu yang tidak. Jika tidak dikompilasi maka memiliki dua perilaku yang valid.

main = disp (DataTypeProxy :: DataTypeProxy 'Constructor)

hanya memiliki satu kemungkinan interpretasi ... tetapi mengharuskan Anda untuk mengirim pada jenis hantu. Itu adalah,

main = disp (DataTypeProxy :: DataTypeProxy 'SomethingElse)

adalah program yang identik pada tingkat istilah, tetapi memiliki perilaku yang berbeda. Itu memecah pada dasarnya semua properti yang bagus seperti parametrik. Pengiriman berbasis Typeclass adalah solusi untuk ini, karena apa contoh dalam efek lingkup perilaku program dengan cara yang dapat diprediksi (Dan semantik).


4
2018-06-13 03:07