gpt4 book ai didi

haskell - 具有代数类型的镜头包

转载 作者:行者123 更新时间:2023-12-03 23:55:55 26 4
gpt4 key购买 nike

我正在使用镜头包进行编码。一切都很顺利,直到我尝试访问代数类型的某个字段:

import Control.Lens

data Type = A { _a :: Char } | B

makeLenses ''Type

test1 = _a (A 'a')
test2 = (A 'a') ^. a

No instance for (Data.Monoid.Monoid Char)
arising from a use of `a'
Possible fix:
add an instance declaration for (Data.Monoid.Monoid Char)
In the second argument of `(^.)', namely `a'
In the expression: (A 'a') ^. a
In an equation for `test2': test2 = (A 'a') ^. a

我可以使用 _a,但我的实际程序中的数据类型要深得多,我打算使用镜头来减少我必须做的工作量。我一直在查看镜头库,但那里有很多东西,我不确定他是否处理过这种情况,或者这只是镜头库不支持的东西。

附带说明一下,如果我实际上使用像 String 这样的幺半群而不是 Char 作为数据类型,那么它会编译并给出正确的答案,我不知道为什么。

编辑:在阅读了 hammar 的评论后,我尝试了这个,这很有效:
test2 = (A 'a') ^? a
test3 = B ^? a

但是对于必须存在的东西来说,从中获得一个可能有点奇怪。

最佳答案

为了回答这个问题,我的问题是我有一个代数类型,其中一些字段在不同的构造函数之间是共同的,但是如果我尝试使用它们,有几个不共享的字段会在运行时消失。

data Exercise =
BarbellExercise {
name :: String,
weight :: Int,
reps :: Int
} |
BodyWeightExercise {
name :: String,
reps :: Int
}

exer1 = BarbellExercise "Squats" 235 15
exer2 = BarbellExercise "Deadlifts" 265 15
exer3 = BodyWeightExercise "Pullups" 12
exer4 = BarbellExercise "Overhead Press" 85 15

workout = [exer1, exer2, exer3, exer4]

test = do
mapM_ displayExercise workout

where
displayExercise x = putStrLn $ "Exercise: " ++ (name x) ++ " You must perform " ++ (show $ reps x) ++ "@" ++ (show $ weight x)

如果我错误地使用了权重函数,这会编译但运行时会死掉。可以理解的错误。当镜头使用模板 haskell 生成实例时,它会注意到这一点并更改其行为以防止错误。您可以删除字段访问器,但在我的情况下,大多数字段在数据类型之间是相同的。一旦我注意到字段不匹配,我应该这样编写数据类型:
data Exercise =
BarbellExercise
String -- ^ name
Int -- ^ reps
Int -- ^ weight
|
BodyWeightExercise
String -- ^ name
Int -- reps


name :: Exercise -> String
name (BarbellExercise n _ _) = n
name (BodyWeightExercise n _) = n

reps :: Exercise -> Int
reps (BarbellExercise _ r _) = r
reps (BodyWeightExercise _ r) = r

通过这种方式,虽然它不太干净,但在编译时会捕获错误。通过强制我自己编写函数,我会在编写它们时注意到任何部分函数。

我真希望 ghc 会警告我。似乎真的很容易检测到这样的事情。

关于haskell - 具有代数类型的镜头包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16205925/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com