从具有函数作为 Haskell 中的字段的数据类型派生 Eq 时出现问题
Problem when deriving Eq from data type with function as field in Haskell
我正在尝试从具有字段功能的数据类型派生 Eq,但没有按预期工作。
我也试过写实例但是还是不行
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 中,唯一合理的含义是 extensional equality),您需要检查它们是否同意 所有可能的输入 .这是一件完全不可行的事情,即使是简单的 Int
输入,但如果参数的类型为 [Char]
.
So, why I need the deriving(Eq)
? I need it because in the main
I check if is Nothing
你完全不需要 Eq
!使用 ==
测试 Maybe
值是否为 Nothing
是无效的,即使在可能的类型上也是如此。您应该改为使用模式匹配
main = do
...
let myConfq = ... :: Maybe Conf
case myConfq of
Nothing -> error "Meh, couldn't have conf"
Just conf -> ...
...或使用更高级别的组合器,可能基于 Maybe
s Applicative
或 Traversable
实例
import Data.Traversable
main = do
...
let myConfq = ... :: Maybe Conf
traverse ... myConfq
我正在考虑允许注释允许您想要的数据类型的字段的想法:Via fields: finer granularity in deriving
想法是定义一个比较总是成功的新类型:
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)
我正在尝试从具有字段功能的数据类型派生 Eq,但没有按预期工作。
我也试过写实例但是还是不行
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 中,唯一合理的含义是 extensional equality),您需要检查它们是否同意 所有可能的输入 .这是一件完全不可行的事情,即使是简单的 Int
输入,但如果参数的类型为 [Char]
.
So, why I need the
deriving(Eq)
? I need it because in themain
I check if isNothing
你完全不需要 Eq
!使用 ==
测试 Maybe
值是否为 Nothing
是无效的,即使在可能的类型上也是如此。您应该改为使用模式匹配
main = do
...
let myConfq = ... :: Maybe Conf
case myConfq of
Nothing -> error "Meh, couldn't have conf"
Just conf -> ...
...或使用更高级别的组合器,可能基于 Maybe
s Applicative
或 Traversable
实例
import Data.Traversable
main = do
...
let myConfq = ... :: Maybe Conf
traverse ... myConfq
我正在考虑允许注释允许您想要的数据类型的字段的想法:Via fields: finer granularity in deriving
想法是定义一个比较总是成功的新类型:
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)