gpt4 book ai didi

haskell - 我可以将这个新类型实现为其他类型的组合吗?

转载 作者:行者123 更新时间:2023-12-04 01:11:17 26 4
gpt4 key购买 nike

我写了一个新类型 Const3这与 Const 非常相似, 但包含三个给定类型参数中的第一个:

newtype Const3 a b c = Const3 { getConst3 :: a }
我可以为这种新类型定义很多有用的实例,但我必须自己完成。
但是,我在类型级别应用的函数类似于函数
\a b c -> a
其中 @pl告诉我相当于 const . const .
两个 (.)const有匹配的新类型包装器: Compose Const .所以我想我可以写:
type Const3 = Compose Const Const
并自动继承有用的实例,例如:
instance Functor (Const m)
instance (Functor f, Functor g) => Functor (Compose f g)
-- a free Functor instance for Const3!
但 GHC 不同意:
const3.hs:5:23:
Expecting one more argument to ‘Const’
The first argument of ‘Compose’ should have kind ‘* -> *’,
but ‘Const’ has kind ‘* -> * -> *’
In the type ‘Compose Const Const’
In the type declaration for ‘Const3’
这似乎与 Compose 的种类有关。和 Const :
*Main> :k Compose
Compose :: (* -> *) -> (* -> *) -> * -> *
*Main> :k Const
Const :: * -> * -> *
所以经过一番搜索,我发现有一个 GHC 扩展名为 PolyKinds这让我可以做类似的事情:
{-# LANGUAGE PolyKinds #-}
newtype Compose f g a = Compose { getCompose :: f (g a) }
newtype Const a b = Const { getConst :: a }
好像魔法一样,这些种类是正确的:
 *Main> :k Compose
Compose :: (k -> *) -> (k1 -> k) -> k1 -> *
*Main> :k Const
Const :: * -> k -> *
但是我还是写不出来 Const3 = Compose Const Const .
const3.hs:12:23:
Expecting one more argument to ‘Const’
The first argument of ‘Compose’ should have kind ‘* -> *’,
but ‘Const’ has kind ‘* -> k0 -> *’
In the type ‘Compose Const Const’
In the type declaration for ‘Const3’
是什么赋予了?有没有一些聪明的方法可以做到这一点,所以我可以获得继承 Functor 的好处等来自 Const 的实例和 Compose ?

(As a side note, the original thought that led me to Const3 was writing:

newtype Const3 a b c = Const3 { getConst3 :: a }

instance Monoid m => Category (Const3 m) where
id = Const3 mempty
Const3 x . Const3 y = Const3 (mappend x y)

capturing the idea that a monoid is a single-object category. It would be nice if there's a solution that still allows me to write the above instance somehow.)

最佳答案

令人困惑的事情——或者,至少,让我困惑的事情——是 *充当具体类型,而不是类型变量。所以没有 PolyKinds , Compose有一种更像:

compose :: (A -> A) -> (A -> A) -> A -> A

至关重要的是,我们无法替换 AA -> A因为它们是不同的类型,所以,按照相同的逻辑,我们不能替换 ** -> *任何一个。

即使是 PolyKinds ,种类还是不对。特别是, Compose预计 (k -> *)作为它的第一个参数,你试图给它 (k -> (k2 -> *)) .

您被迫返回 * 的原因kind 是因为您使用的是 newtypes ,并且 newtypes 必须返回一个具体的类型(即类型 * )。我试图通过转动 Compose 来克服这个问题。变成一个类型同义词,最终完全符合我们想要的类型(使用 PolyKinds ):
type Compose f g a = (f (g a))

λ> :k Compose
Compose :: (k1 -> k) -> (k2 -> k1) -> k2 -> k

但是,使用它仍然给我一个类似的错误,我不确定我们是否可以让它正常工作。出现问题是因为应用 Compose到第一个 Const给我们一种带有 * 的在其中,可能是因为像这样的类型别名的限制:
λ> :k Compose Const
Compose Const :: (k -> *) -> k -> k1 -> *

关于haskell - 我可以将这个新类型实现为其他类型的组合吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32106435/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com