2015-07-26 26 views
6

servant hakkında heyecanlıyım ve dahili typelevel sihirbazının yolunda gitmediği sürece iyiyim ve Beni şaşırtan tek şey, genel API'de type-proxy'un kullanılmasıdır. İşte code var:Data.Proxy servant'ın public API'sinde (neden Proxy with ScopedTypeVariables çalışmaz)

serve :: HasServer layout => Proxy layout -> Server layout -> Application 
serve p server = toApplication (runRouter (route p (return (RR (Right server))))) 

Anlıyorum gibi, tip-yakınlık oldukça basit şey vardır ve bu tip bir değere sahip olmadığında bir tür taşımak için ihtiyaç vardır. Öyleyse, Server'ın tip parametresinde zaten düzen türü olduğunda, düzen türü taşıyan bir proxy'yi neden geçmeliyiz?

{-# LANGUAGE ScopedTypeVariables #-} 

serve :: forall layout . HasServer layout => Server layout -> Application 
serve server = toApplication (runRouter (route p (return (RR (Right server))))) 
    where 
    p :: Proxy layout 
    p = Proxy 

Ve şaşırtıcı bana (düzen tür uyuşmazlığını şey söylüyorum) derlenmeyecektir: Ben buna klonlama hizmetçinin repo ve değişen kod denedim. Ama neden, yerel p'm sunucu ile aynı düzen türüne sahip olmamalıdır (ScopedTypeVariables açıkken)?

+0

Çalıştırılabilir örnek, lütfen. –

+0

@ AndrásKovács, soru temel olarak (ve hangi durumlarda) yerel aynı tip taşıyan p parametresi olarak harici olarak aktardığımızla aynı değildir. Üzgünüm, ama neler olduğunu anlayamadığımdan, 'git clone https://github.com/haskell-servant/servant.git' olmaksızın bunu daha basit durumlarla nasıl yeniden üreteceğimi bilmiyorum. – aemxdp

cevap

7

Türü aileler, enerjik değildir ve Server'un arkasında bir tane vardır. Bu işleve bir Server MyAPI iletirseniz, GHC, layout = MyAPI sonucunu çıkaramaz. Maalesef burada bir Proxy'a ihtiyacımız var. Biz injective tip aileleri olsa bile, bu yardımcı olmaz:

type API1 = Get '[JSON] User 
type API2 = Post '[JSON] User 

Bu iki API aslında Serverinjective olamaz gerektiğini bize gösteren, öyle ki Server API1 = Server API2 ama API1 /= API2 bulunmaktadır. Hedeflemek istediğimiz API türünü ayırmanın en kolay yolu Proxy'dur. Öte yandan, çoğu zaman API'larımızın çeşitli hizmet paketlerinde sorduğu tek şey bu.

+0

, https://wiki.haskell.org/GHC/Type_families#Injectivity.2C_type_inference.2C_and_ambiguity bakın –

1

Server o HasServer sınıfta ServerT ilişkili türü için bir tür eşanlamlı olduğunu, bir tür yapıcı değildir. Bu nedenle, Server layout'da gerçekleşen layout, HasServer kısıtlamasını ortadan kaldırmaz. HasServer layout örneğimiz varsa, yalnızca Server layout türünü çözebiliriz.

+1

Haskell'in tasarımcılarının, eşanlamlı tür eşanlamlı olarak yazıldığını düşünmeye başladım (ve dolayısıyla aileleri yazın). Büyük harfle başlayan her şeyin bir kurucu olduğu kanunu ihlal ediyorlar. Onların seçimi, belirsizliğe değmez gibi görünen, en üst seviyede 'forall' un ihmal edilmesinin şüpheli kısasını sağlar. tipi aileleri ve İnjektif daha uzun bir açıklama için – dfeuer