我正在嘗試從資料型別派生 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)?我需要它,因為我主要檢查 if is 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
uj5u.com熱心網友回復:
是什么讓您認為這應該是可能的?如果您的型別包含一個函式欄位,那么比較您的型別的值是否相等至少與比較函式是否相等一樣困難。但是要檢查兩個函式是否相等(在 Haskell 中,唯一有意義的含義是外延相等),您需要檢查它們是否同意所有可能的輸入。這是一件完全不可行的事情,即使是簡單的Int輸入,但如果引數有 type 則肯定是這樣[Char]。
那么,為什么我需要
deriving(Eq)? 我需要它,因為在main我檢查是否是Nothing
你完全不需要那個Eq!測驗一個Maybe值是否Nothing通過 using==是無效的,即使在那些可能的型別上也是如此。您應該改為使用任一模式匹配
main = do
...
let myConfq = ... :: Maybe Conf
case myConfq of
Nothing -> error "Meh, couldn't have conf"
Just conf -> ...
...或使用更高級別的組合器,可能基于MaybesApplicative或Traversable實體
import Data.Traversable
main = do
...
let myConfq = ... :: Maybe Conf
traverse ... myConfq
uj5u.com熱心網友回復:
我正在考慮允許注釋資料型別的欄位的想法,這些欄位將允許您想要的內容:通過欄位:推導中更精細的粒度
這個想法是定義一個比較總是成功的新型別:
newtype Ignore a = Ignore a
instance Eq (Ignore a) where
_ == _ = True
instance Ord (Ignore a) where
compare _ _ = EQ
然后只注釋函式欄位;然后當我們派生資料型別的實體時,操作欄位的實體(==) @([Char] -> Char)實際上是通過 newtype 執行的(==) @(via Ignore):
data Conf = Conf
{ rule :: [Char] -> Char
via Ignore ([Char] -> Char)
, start :: Int
, ..
}
deriving
stock (Eq, Ord)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/440924.html
