2016-12-16 13 views
7

एक comment उपयोगकर्ता 2426021684 द्वारा मुझे जांच करने के लिए कि क्या यह एक प्रकार समारोह साथ आने के लिए F ऐसी है कि F c1 c2 fa दर्शाता संभव हो गया था नेतृत्व कि कुछ f और a के लिए:क्या एक प्रकार के आवेदन में बाधाओं को लागू करने का कोई सामान्य तरीका है?

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

यह पता चला है कि सबसे सरल इसका आरएम काफी आसान है। हालांकि, मुझे एक पॉली-टाइपेड संस्करण लिखने के तरीके के बारे में काम करना मुश्किल लगता है। सौभाग्य से, मैं एक रास्ता खोजने में कामयाब रहा क्योंकि मैं इस सवाल को लिख रहा था।

उत्तर

6

सबसे पहले, कुछ बॉयलरप्लेट:

{-# 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 

अब मनमाना प्रकार पर अनुप्रयोगों deconstruct करने के लिए परिवारों टाइप करें।

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

अब एक अत्यंत सामान्य प्रकार का कार्य, प्रश्न का उत्तर देने के लिए आवश्यक से अधिक सामान्य है। लेकिन यह एप्लिकेशन के दोनों घटकों को शामिल करने वाली बाधा की अनुमति देता है।

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

मैं वर्गों मैच के लिए बिना बाधा कार्यों की पेशकश, इसलिए यहाँ पसंद नहीं है G की एक प्रथम श्रेणी संस्करण है। कुछ नमूना F का उपयोग करता

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 

यहाँ हैं::

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

यह G और एक सहायक वर्ग का उपयोग कर F व्यक्त करने के लिए संभव है

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

अगर आप एक inflix के रूप में एफसी का उपयोग यह बेहतर लग रहा है ऑपरेटर। – 2426021684

+0

'((~) या तो) \' एफसी \ 'ईक \' एफसी \ 'ईक' – 2426021684

+0

@ 2426021684, अच्छा बिंदु। – dfeuer

संबंधित मुद्दे

 संबंधित मुद्दे