当前位置: 首页 > 知识库问答 >
问题:

通过GeneralizedNewtypeDeriving派生实例时使用自定义实例

叶鹭洋
2023-03-14

假设我们有一个typeclass类(a a,B a)=>C a where。使用NewType将允许我们克隆一个数据类型,然后通过GeneralizedNewTypeDeriving语言扩展自动派生实例(请参见如何编写可派生类?以及使用相同的内部表示和最小的样板处理多个类型?)。

问题:是否可以让ghc自动派生AC,但在派生C时使用我们自己指定的B实现?

例如,以下代码(其中A=planetB=liveC=description)不能按预期工作:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
module Main (main) where

data Cat = Cat String
newtype Dolphin = Dolphin Cat deriving (Planet)

------------------------------------------------

class Planet a where
  planet :: a -> String

class Lives a where
  lives :: a -> String

class (Planet a, Lives a) => Description a where
  description :: a -> String

------------------------------------------------

instance Planet Cat where
  planet _ = "lives on planet earth,"

instance Lives Cat where
  lives _ = "lives on land"

instance Description Cat where
  description a = (planet a) ++ (lives a)

------------------------------------------------

instance Lives Dolphin where
  lives _ = "lives in the sea"

--want the following derivation to use the instance of 
--"Lives" for "Dolphin" above
deriving instance Description Dolphin

------------------------------------------------

main = do
  print $ description (Cat "test")
  -- > "lives on planet earth,lives on land"
  -- OK
  print $ description (Dolphin (Cat "test"))
  -- > "lives on planet earth,lives on land"
  -- NOT OK. Want "lives on planet earth,lives in the sea"

我期望/想要的是在派生description时调用livesdolphin实例

显然,以下程序可以工作,但它需要为dolphin显式实例化description:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
module Main (main) where

data Cat = Cat String
newtype Dolphin = Dolphin Cat deriving (Planet)

------------------------------------------------

class Planet a where
  planet :: a -> String

class Lives a where
  lives :: a -> String

class (Planet a, Lives a) => Description a where
  description :: a -> String

------------------------------------------------

instance Planet Cat where
  planet _ = "lives on planet earth,"

instance Lives Cat where
  lives _ = "lives on land"

instance Description Cat where
  description a = (planet a) ++ (lives a)

------------------------------------------------

instance Lives Dolphin where
  lives _ = "lives in the sea"

instance Description Dolphin where
  description a = (planet a) ++ (lives a)

------------------------------------------------

main = do
  print $ description (Cat "test")
  -- > "lives on planet earth,lives on land"
  --[OK]
  print $ description (Dolphin (Cat "test"))
  -- > "lives on planet earth,lives in the sea"
  --[OK]
instance Lives Dolphin where
  lives _ = "lives in the sea"

然后ghc抱怨:

Main.hs:36:1:
    No instance for (Lives Dolphin)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘Description Dolphin’

奇怪的是,如果ghc没有在Dolphindescription的(自动)派生中使用instance Lives Dolphin的话,它会抱怨没有instance Lives Dolphin

共有1个答案

祁曦哲
2023-03-14

请考虑以下内容:

newtype ProcessID = PID Int deriving Eq

这样做的目的是编写一个实例

instance Eq PID where
  (PID x) == (PID y)    =    x == y

换句话说,当您对pid调用==时,它会将其解包装为普通的int,然后对其执行==

(或者这是你想要解决的某个更复杂问题的简化?)

 类似资料:
  • 在Haskell中,当定义一个数据类型时,您可以选择自动派生一些实例,但我是否可以推迟自动派生,甚至可以将其放到另一个库中? 这里有一个例子: 在Haskell自动派生是一个实时节省! 最好用丢失的实例修补实际中的问题。 认为有孤立实例是不好的。实例声明最好放在定义类型类或数据类型的模块中。 在我的例子中,我不能遵循最佳实践,因为type类与数据类型无关。我怀疑type class模块和data

  • 我对Kafka很陌生。我想在我的spring项目中使用kafka生产者/消费者来替换activeMQ(jms)。我需要的是一个Kafka生产者将我的消息对象发布到一个主题,一个消费者从该主题订阅它。 首先是我的自定义编码器,解码器也是这样(对于我的消息类ConfigurationActionMsg): 下面是我对处理器和消费者的配置 我不确定这是否是实例化生产者/消费者的适当方法。但这种方式行不通

  • 本文向大家介绍Android自定义ActionBar实例,包括了Android自定义ActionBar实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android自定义ActionBar的实现方法。分享给大家供大家参考。具体实现方法如下: Android 3.0及以上已经有了ActionBar的API,可以通过引入support package在3.0以下的平台引用这些API,但这儿

  • 本文向大家介绍Android种使用Notification实现通知管理以及自定义通知栏实例(示例四),包括了Android种使用Notification实现通知管理以及自定义通知栏实例(示例四)的使用技巧和注意事项,需要的朋友参考一下 示例一:实现通知栏管理 当针对相同类型的事件多次发出通知,作为开发者,应该避免使用全新的通知,这时就应该考虑更新之前通知栏的一些值来达到提醒用户的目的。例如我们手机

  • 本文向大家介绍AngularJS中过滤器的使用与自定义实例代码,包括了AngularJS中过滤器的使用与自定义实例代码的使用技巧和注意事项,需要的朋友参考一下 前言 相信大家都知道过滤器的使用:一种是在html中的使用,一种是在js代码中的使用,下面我们来通过实例深入了解。 实例代码 运行效果图如下 总结 以上就是这篇文章的全部内容,希望对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交

  • 我试图通过Java代码启动一个EC2实例。我在我的项目中添加了这个maven依赖项: https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-ec2/1.11.308 有人能告诉我如何指定实例类型吗?