연결에 대한 좋은 사실은 방정식에서 두 가지 변수를 아는 경우입니다.
a ++ b = c
그런 다음 세 번째를 알고 있습니다.
나는 기능적으로 의존성을 사용하기 위해이 아이디어를 내 자신의 concat에서 포착하고 싶습니다.
{-# Language DataKinds, GADTs, FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, PolyKinds, TypeOperators, UndecidableInstances #-}
import Data.Kind (Type)
class Concatable
(m :: k -> Type)
(as :: k)
(bs :: k)
(cs :: k)
| as bs -> cs
, as cs -> bs
, bs cs -> as
where
concat' :: m as -> m bs -> m cs
이제는 이기종 목록을 다음과 같이 활용합니다.
data HList ( as :: [ Type ] ) where
HEmpty :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
그러나 나는 이러한 선언 할 때 Concatable
나는 문제가있는
instance Concatable HList '[] bs bs where
concat' HEmpty bs = bs
instance
( Concatable HList as bs cs
)
=> Concatable HList (a ': as) bs (a ': cs)
where
concat' (HCons head tail) bs = HCons head (concat' tail bs)
세 번째 기능 의존성을 만족시키지 않습니다. 또는 오히려 컴파일러는 우리가하지 않는다고 생각합니다. 이는 컴파일러가 두 번째 인스턴스에서 그렇다고 생각하기 때문입니다 bs ~ (a ': cs)
. 그리고 경우에 해당 될 수 있습니다 Concatable as (a ': cs) cs
.
세 가지 종속성이 모두 충족되도록 인스턴스를 조정하려면 어떻게해야합니까?
luqui 말한 확장하려면 : 우리가 알고있는 상상
—
chi
bs
하고 cs
, 즉 우리가 재구성하려면, 우리가 fundep을 악용하려는 as
. 결정적인 방식으로이를 수행하기 위해 단일 인스턴스에 커밋하고 해당 레시피를 따를 수있을 것으로 기대합니다. 구체적으로, 가정 bs = (Int ': bs2)
및 cs = (Int ': cs2)
. 어떤 인스턴스를 선택합니까? 이 같은 가능성이 Int
있는가 cs
에서 온다 bs
(그리고 as
비어 있습니다). as
대신 (비어 있지 않음)에서 왔으며 나중에 Int
다시 나타날 수도 cs
있습니다. 우리는 더 깊이 파고 들어야 cs
하고, GHC는 그렇게하지 않을 것입니다.
대략적으로 말하면, GHC는 인스턴스로부터 간단한 형태의 유도를 사용하여 증명할 수있는 자금을 수용 할 것입니다. 여기서, 그중 하나는 증명을 위해 일종의 이중 유도가 필요하며 컴파일러는 그렇게 멀지 않습니다.
—
chi
bs cs -> as
우리가 로컬이 아닌 정보를 필요로하기 때문에,bs
그리고cs
여부를 결정하는as
단점 또는 전무을해야합니다. 이 정보를 나타내는 방법을 찾아야합니다. 직접 추론 할 수 없을 때이를 보장하기 위해 형식 서명에 어떤 컨텍스트를 추가합니까?