2

我正在尝试在 Idris 中实现最简单的 profunctor optic。Iso 是一个在所有 profunctor 中都应该是多态的函数。我认为这是正确的语法。

一切都进行类型检查,除了最终测试。

interface Profunctor (p : Type -> Type -> Type) where
  dimap : (a' -> a) -> (b -> b') -> p a b -> p a' b'

Iso : Type -> Type -> Type -> Type -> Type
Iso a b s t = {p : Type -> Type -> Type} -> Profunctor p => p a b -> p s t

-- A pair of functions
data PairFun : Type -> Type -> Type -> Type -> Type where
  MkPair : (s -> a) -> (b -> t) -> PairFun a b s t

-- PairFun a b s t  is a Profunctor in s t
Profunctor (PairFun a b) where
  dimap f g (MkPair get set) = MkPair (get . f) (g . set)

-- Extract a pair of functions from an Iso
fromIso : Iso a b s t -> PairFun a b s t
fromIso iso = iso (MkPair id id)

-- Turn a pair of functions to an Iso
toIso : PairFun a b s t -> Iso a b s t
toIso (MkPair get set) = dimap get set

-- forall p. Profunctor p => p Int Int -> p Char String
myIso : Iso Int Int Char String
myIso = toIso (MkPair ord show)

x : PairFun Int Int Char String
x = fromIso myIso

我收到这个错误。看起来 Idris 正在抱怨 p1 是 Profunctor 的假设,但这是 Iso 定义中的约束。

Can't find implementation for Profunctor p1
    Type mismatch between
            p1 Int Int -> p1 Char String (Type of myIso p1
                                                         constraint)
    and
            p Int Int -> p Char String (Expected type)
                
     Specifically:
            Type mismatch between
                    p1 Int Int
            and
                    p Int Int
4

1 回答 1

3

以下代码在 Idris 2 版本 0.3 中为我工作。这是 Idris 2 的一个相当旧的版本,但它可能也适用于更新的版本。

interface Profunctor (0 p : Type -> Type -> Type) where
  dimap : (a' -> a) -> (b -> b') -> p a b -> p a' b'

Iso : Type -> Type -> Type -> Type -> Type
Iso a b s t = {0 p : Type -> Type -> Type} -> Profunctor p => p a b -> p s t

data PairFun : Type -> Type -> Type -> Type -> Type where
  MkPair : (s -> a) -> (b -> t) -> PairFun a b s t

Profunctor (PairFun a b) where
  dimap f g (MkPair get set) = MkPair (get . f) (g . set)

fromIso : Iso a b s t -> PairFun a b s t
fromIso iso = iso (MkPair id id)

toIso : PairFun a b s t -> Iso a b s t
toIso (MkPair get set) = dimap get set

myIso : Iso Int Int Char String
myIso = toIso (MkPair ord show)

x : PairFun Int Int Char String
x = fromIso myIso

不幸的是,我不知道如何在 Idris 1 中完成这项工作。问题似乎是 的生成性p:阐述者没有p1 = p2p1 a b = p2 a b. 在任何 Idrises 中,这通常不成立,因为p1并且p2可以是任意函数。Idris 2 似乎p1 = p2无论如何都会在某个时候继续前进。这是一个方便的特性,代价是推理的一些鲁棒性。

上述代码中的无关注释p与我刚才提到的生成性问题无关,它们只是重现 Idris 1 和 GHC 行为所必需的。在 Idris 2 中,隐式引入的变量总是具有0多重性,因此我们也必须进行p擦除,以便能够将其应用于0类型参数。此外,0 p匹配 Idris 1 / GHC 行为,其中类型通常被擦除。在 Idris 2 中,类型仅在与 绑定时才会被擦除0

于 2021-12-02T07:44:27.677 回答