2016-12-16 35 views
7

Bir kullanıcı 2426021684 tarafından comment o göstermektedir F böyle F c1 c2 fa bir tip fonksiyonu ile gelip mümkün olup olmadığını araştırmak için götürdü bazı f ve a için:Bir tür uygulamaya kısıtlamaları uygulamak için genel bir yol var mı?

  1. fa ~ f a
  2. c1 f
  3. c2 a

En basit Bunun rm'si oldukça kolaydır. Bununla birlikte, çok kibar bir versiyonun nasıl yazılacağını öğrenmek oldukça zor. Neyse ki, bu soruyu yazarken bir yol bulmayı başardım.

cevap

6

Birincisi, bazı klişe:

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE ConstraintKinds #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses #-} 
{-# LANGUAGE PolyKinds #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE ScopedTypeVariables #-} 

module ConstrainApplications where 

import GHC.Exts (Constraint) 
import Data.Type.Equality 

Şimdi keyfi tür etkinliklerde uygulamaları yapısızlaştırmak aileleri yazın.

type family GetFun a where 
    GetFun (f _) = f 
type family GetArg a where 
    GetArg (_ a) = a 

Şimdi bu soruya cevap vermek için gerekenden daha genel bir genel işlev. Ancak bu, uygulamanın her iki bileşenini de içeren bir kısıtlamaya izin verir. Ben, işte maç için sınıflar olmadan kısıt fonksiyonları sunan sevmiyorum

type G (cfa :: (j -> k) -> j -> Constraint) (fa :: k) 
    = (fa ~ (GetFun fa :: j -> k) (GetArg fa :: j) 
    , cfa (GetFun fa) (GetArg fa)) 

G bir birinci sınıf versiyonu. İşte

class (cf f, ca a) => Q cf ca f a 
instance (cf f, ca a) => Q cf ca f a 

type F cf ca fa = G (Q cf ca) fa 

class F cf ca fa => FC cf ca fa 
instance F cf ca fa => FC cf ca fa 

olan bazı örnek F ait kullanır:

class G cfa fa => GC cfa fa 
instance G cfa fa => GC cfa fa 

O G ve bir yardımcı sınıfını kullanarak F ifade etmek mümkündür

t1 :: FC ((~) Maybe) Eq a => a -> a -> Bool 
t1 = (==) 

-- In this case, we deconstruct the type *twice*: 
-- we separate `a` into `e y`, and then separate 
-- `e` into `Either x`. 
t2 :: FC (FC ((~) Either) Show) Show a => a -> String 
t2 x = case x of Left p -> show p 
       Right p -> show p 

t3 :: FC Applicative Eq a => a -> a -> GetFun a Bool 
t3 x y = (==) <$> x <*> y 
+0

bir inflix olarak FC kullanmak eğer iyi görünüyor Şebeke. – 2426021684

+0

((~) Ya her ikisi de) \ 'FC \' Eq \ 'FC \' Eq' – 2426021684

+0

@ 2426021684, iyi nokta. – dfeuer