[英]Constraint implication as a constraint
如何將 Haskell 中的約束蘊涵編碼為新約束? 在我的例子中,我想要求每個Functor cdf
需要Obj cx
暗示Obj c (fx)
。 我正在為所有forall x . Obj cx => Obj d (fx)
編寫約束forall x . Obj cx => Obj d (fx)
forall x . Obj cx => Obj d (fx)
。
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE QuantifiedConstraints #-}
import Prelude hiding (id, Functor, fmap)
import Data.Kind
class Category c where
type Obj c a :: Constraint
id :: (Obj c x) => c x x
comp :: (Obj c x) => c y z -> c x y -> c x z
class ( Category c, Category d, forall x . Obj c x => Obj d (f x))
=> Functor c d f where
fmap :: (Obj c x, Obj c y) => c x y -> d (f x) (f y)
doublefmap :: forall c f x . (Category c , Functor c c f, Obj c x)
=> c x x -> c (f (f x)) (f (f x))
doublefmap = fmap @c @c @f . fmap @c @c @f
但這會產生以下錯誤:
Minimal.hs:27:14: error:
• Could not deduce: Obj c (f x) arising from a use of ‘fmap’
from the context: (Functor c c f, Obj c x)
bound by the type signature for:
doublefmap :: forall (c :: * -> * -> *) (f :: * -> *) x.
(Category c, Functor c c f, Obj c x) =>
c x x -> c (f (f x)) (f (f x))
at Minimal.hs:(25,1)-(26,44)
• In the first argument of ‘(.)’, namely ‘fmap @c @c @f’
In the expression: fmap @c @c @f . fmap @c @c @f
In an equation for ‘doublefmap’:
doublefmap = fmap @c @c @f . fmap @c @c @f
• Relevant bindings include
doublefmap :: c x x -> c (f (f x)) (f (f x))
(bound at Minimal.hs:27:1)
我在這里做錯了什么? 我應該給編譯器什么額外的提示? 有沒有更好的方法來實現這一目標?
我的猜測是我需要使用Data.Constraint
和:-
,但是如何使用?
以下似乎有效,但我不知道這是否更簡單。 它使用來自Data.Constraint
的運算符(\\\\)
。
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE QuantifiedConstraints #-}
import Prelude hiding (id, Functor, fmap)
import Data.Constraint
class Category c where
type Obj c a :: Constraint
id :: (Obj c x) => c x x
comp :: (Obj c x) => c y z -> c x y -> c x z
class (Category c, Category d) => Functor c d f where
fobj :: forall x. Obj c x :- Obj c (f x)
fmap :: (Obj c x, Obj c y) => c x y -> d (f x) (f y)
doublefmap :: forall c f x . (Category c , Functor c c f, Obj c x)
=> c x x -> c (f (f x)) (f (f x))
doublefmap = (fmap @c @c @f . fmap @c @c @f) \\ fobj @c @c @f @x
這是不使用Data.Constraint
的第二種解決方案(至少對我而言)似乎更優雅一些。
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE ConstraintKinds #-}
import Prelude hiding (id, Functor, fmap)
class Category objc c where
id :: (objc x) => c x x
comp :: (objc x) => c y z -> c x y -> c x z
class (Category objc c, Category objd d, forall x . (objc x) => objd (f x))
=> Functor objc c objd d f where
fmap :: (objc x, objc y) => c x y -> d (f x) (f y)
doublefmap :: forall c f x objc objd . (Category objc c , Functor objc c objc c f, objc x)
=> c x x -> c (f (f x)) (f (f x))
doublefmap = (fmap @objc @c @objc @c @f . fmap @objc @c @objc @c @f)
如果有人可以改進這一點,我會很高興。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.