2016-12-16 22 views
7

Một comment của thành viên 2426021684 dẫn tôi đến điều tra xem liệu nó đã có thể đưa ra một chức năng loại FF c1 c2 fa chứng minh rằng đối với một số fa:Có cách nào chung để áp dụng các ràng buộc cho một ứng dụng kiểu?

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

Hóa ra là đơn giản nhất rm của điều này là khá dễ dàng. Tuy nhiên, tôi thấy khá khó khăn để tìm ra cách viết một phiên bản nhiều loại. May mắn thay, tôi đã tìm cách để viết câu hỏi này.

Trả lời

6

Thứ nhất, một số soạn sẵn:

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

Bây giờ gõ các gia đình để mổ xẻ các ứng dụng tại các loại tùy ý.

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

Hiện tại, chức năng cực kỳ chung chung, cần thiết hơn để trả lời câu hỏi. Nhưng điều này cho phép một ràng buộc liên quan đến cả hai thành phần của ứng dụng.

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

Tôi không thích các chức năng ràng buộc cung cấp mà không có lớp học phù hợp, vì vậy đây là phiên bản hạng nhất của G.

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

Có thể bày tỏ F sử dụng G và một lớp phụ trợ:

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 

Dưới đây là một số mẫu sử dụng của 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

Có vẻ tốt hơn nếu bạn sử dụng FC như một inflix nhà điều hành. – 2426021684

+0

'((~) Hoặc) \' FC \ 'Eq \' FC \ 'Eq' – 2426021684

+0

@ 2426021684, điểm tốt. – dfeuer

Các vấn đề liên quan