gpt4 book ai didi

haskell - 为类型同义词编写仿函数实例并感到困惑

转载 作者:行者123 更新时间:2023-12-03 07:52:08 25 4
gpt4 key购买 nike

我正在尝试实现一个通用的类似环形的东西,并将其应用于 Paul Hudak 在《 haskell 音乐学院》一书中描述的音乐数据结构。自然有很多半群/幺半群省略了恶作剧,但我有以下相关代码:

newtype Duo     a b     = Duo     {duo1     :: a} -- A ring-like structure

data Song a =
Primitive a
| Song a :+: Song a -- Composing Music Sequentially
| Song a :=: Song a deriving Eq -- Composing Music Concurrently (in parallel)

instance Functor Song where
fmap f (x :+: y) = fmap f x :+: fmap f y
fmap f (x :=: y) = fmap f x :=: fmap f y
fmap f (Primitive x) = Primitive $ f x

newtype Concurrent a = Concurrent {fromConcurrent :: Song a} deriving (Show)
newtype Sequential a = Sequential {fromSequential :: Song a} deriving (Show)

type Music a = Duo (Maybe (Concurrent a)) (Maybe (Sequential a))

我正在尝试编写一个用于音乐的 Functor 实例,因为 Duo 没有 Functor,我认为这不会成为问题。

我编写了以下实现:

instance Functor Music where
fmap :: (a -> b) -> Music a -> Music b
fmap f = Duo . fmap (fmap f . fromConcurrent) . duo1

但我收到以下错误:

• The type synonym ‘Music’ should have 1 argument, but has been given none
• In the instance declaration for ‘Functor Music’
| 167 | instance Functor Music where
| ^^^^^^^^^^^^^

也许问题只是我本质上只是为 Duo 的一个子集编写一个 Functor,也许只有当我将音乐作为一个新类型而不仅仅是一个类型同义词时,这才有效。我真的希望避免这种情况,因为这段代码中的包装器数量已经非常多了,我真的不想再添加另一个。也许你们都可以想出一种方法来为 Duo 实现一个有意义的仿函数,并使这一切都有效?

我真的不明白的一件事是为什么它让我制作一个实例来展示:

instance (Show a) => Show (Music a) where
show (Duo Nothing) = "Silence"
show (Duo (Just (Concurrent x))) = show x

最佳答案

不幸的是,Haskell 中不允许这种类型级别的抽象。但我认为您可能在数据类型设计中的某个地方犯了某种概念错误。扩展类型,自 Duo只有一个字段,我们会有:

Music a ~= Duo (Maybe (Concurrent a)) (Maybe (Sequential a))
~= Maybe (Concurrent a)
~= Maybe (Song a)

这真的是你想要的吗?

万一发生这种情况,我想我会很想去掉中间商。

data Music a = Silence | Sound (Song a)
instance Functor Music where
fmap f Silence = Silence
fmap f (Sound notes) = Sound (fmap f notes)

如果这是预期行为,但您必须保留中间商,newtype是前进的方向。

很可能这不是您想要的 Music为了表现得更好,我们可能会给您更多/更好的建议,但我们需要更多地了解您的意图 Duo的意思。

关于您对 Show 的编辑/评论:在你的Show例如,您可以将类型参数包含到 MusicFunctor 的问题实例正是您包含参数的事实。在 Show例如,因为参数可用,编译器可以简单地扩展类型别名,因此该行

instance Show a => Show (Music a)

在编译器关心的各个方面都与该行相同

instance Show a => Show (Duo (Maybe (Concurrent a)) (Maybe (Sequential a)))

在您的 Functor 中但是,例如,编译器无法扩展类型别名,因为您尚未提供类型参数。您可以想象向 Haskell 添加类型级 lambda,这样您就可以拥有 instance Functor Music意思是这样的

instance Functor (\a -> Duo (Maybe (Concurrent a)) (Maybe (Sequential a)))

但这有一些严重的问题。添加它的幼稚方式导致您需要在类型检查期间进行高阶统一,这是不可判定的。

关于haskell - 为类型同义词编写仿函数实例并感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76933358/

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