我正试图从数据类型中导出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 -> ...
或者使用更高级别的组合子,可能基于Maybe
的Applicative
或Traversable
实例
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)