Ответ 1
Как раз так, что на это отвечает, моя проблема заключалась в том, что у меня был алгебраический тип, в котором некоторые поля были между разными конструкторами, но было несколько полей, которые не были разделены, погибли бы во время выполнения, если бы я попытался их использовать.
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 предупредил меня. Похоже, было бы очень легко обнаружить такую вещь.