从Haskell中函数为字段的数据类型派生Eq时出现的问题



我正试图从数据类型中导出Eq,函数作为字段,但没有按预期工作。

我也试着写te实例,但仍然无法使用

data Conf = Conf {
rule :: ([Char] -> Char),
start :: Int,
numLines :: Double,
window :: Int,
move :: Int,
actualLine :: Int,
lastLine :: String
} deriving (Eq)

这是一个由wolfram金字塔组成的印刷图形项目,例如,规则是:

rule30 :: [Char] -> Char
rule30 "***" = ' '
rule30 "** " = ' '
rule30 "* *" = ' '
rule30 "*  " = '*'
rule30 " **" = '*'
rule30 " * " = '*'
rule30 "  *" = '*'
rule30 "   " = ' '
rule30 _     = ' '

有很多规则需要遵循,正是出于这个原因,我想保存";函数指针";直接在Conf数据类型中。

那么,为什么我需要推导(Eq(?我需要它,因为在主要情况下,我会检查是否为Nothing(错误处理检查,例如,如果用户设置了一个坏规则…(

错误消息:

src/Wolf.hs:24:13: error:
• No instance for (Eq ([Char] -> Char))
arising from the first field of ‘Conf’ (type ‘[Char] -> Char’)
(maybe you haven't applied a function to enough arguments?)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Eq Conf)
|
24 | } deriving (Eq)
|             ^^

我错过了什么?x

是什么让你认为这应该是可能的?如果您的类型包含函数字段,那么比较您类型的值是否相等至少与比较函数是否相等一样困难。但要检查两个函数是否相等(在Haskell中,唯一合理的含义是外延相等(,您需要检查它们在所有可能的输入上是否一致。即使对于简单的Int输入,但如果参数的类型为[Char],这也是完全不可行的。

那么,为什么我需要deriving(Eq)?我需要它,因为在main中我检查是否是Nothing

您完全不需要Eq!使用==测试Maybe值是否为Nothing是无效的,即使在可能的类型上也是如此。您应该使用任一模式匹配

main = do
...
let myConfq = ... :: Maybe Conf
case myConfq of
Nothing -> error "Meh, couldn't have conf"
Just conf -> ...

或者使用更高级别的组合子,可能基于MaybeApplicativeTraversable实例

import Data.Traversable
main = do
...
let myConfq = ... :: Maybe Conf
traverse ... myConfq

我正在考虑这样的想法,即允许注释数据类型的字段,从而允许您想要的内容:通过字段:在导出时更细粒度

这个想法是定义一种新的类型,在这种类型中,比较总是成功的:

newtype Ignore a = Ignore a
instance Eq (Ignore a) where
_ == _ = True
instance Ord (Ignore a) where
compare _ _ = EQ

然后仅注释功能字段;那么,当我们导出数据类型的实例时,操纵字段(==) @([Char] -> Char)的实例实际上是通过新类型(==) @(via Ignore):执行的

data Conf = Conf
{ rule  :: [Char] -> Char
via Ignore ([Char] -> Char)
, start :: Int
, ..
}
deriving
stock (Eq, Ord)

相关内容

  • 没有找到相关文章

最新更新