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
bir inflix olarak FC kullanmak eğer iyi görünüyor Şebeke. – 2426021684
((~) Ya her ikisi de) \ 'FC \' Eq \ 'FC \' Eq' – 2426021684
@ 2426021684, iyi nokta. – dfeuer