Skip to content

Commit 428209e

Browse files
committed
copilot-core: Warn about future generic default for updateField. Refs #564.
Currently, using structs in Copilot requires defining instances of several type classes. Defining those instances is unnecessarily cumbersome, and it exposes the user to a substantial amount of Haskell even when they want to stay at the level of the Copilot language. In the previous commit, we added `Generic`-based defaults for several type class methods, including the `updateField` method of `Struct`. In the future, we plan to change the default implementation for `updateField` such that it will require a `Generic` instance. This will break any existing `Struct` instance that omits an implementation of `updateField` and also does not define a `Generic` instance for the struct data type. Unfortunately, there does not appear to be a way for GHC to warn about this combination of properties. This commit adds a verbal warning to the `updateField` Haddocks to make users aware of this potential problem.
1 parent b447d1c commit 428209e

File tree

1 file changed

+24
-13
lines changed
  • copilot-core/src/Copilot/Core

1 file changed

+24
-13
lines changed

copilot-core/src/Copilot/Core/Type.hs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,35 @@ class Struct a where
7070
toValues :: a -> [Value a]
7171

7272
-- | Update the value of a struct field. This is only used by the Copilot
73-
-- interpreter, so if you do not plan to use the interpreter, it is safe to
74-
-- omit an implementation of this method.
73+
-- interpreter.
7574
--
76-
-- In order to implement 'updateField', you should do the following for each
77-
-- 'Field' in a struct:
75+
-- If you do not plan to use the interpreter, you can omit an implementation
76+
-- of this method. If you do so, it is recommended that you derive a 'Generic'
77+
-- instance for the struct data type. This is because in a future release, the
78+
-- default implementation of 'updateField' (which will be picked if there is
79+
-- not a manually written implementation) will be changed to require a
80+
-- 'Generic' instance.
7881
--
79-
-- 1. Check that the name of the 'Field' matches the name of the supplied
80-
-- 'Value' (using 'GHC.TypeLits.sameSymbol').
82+
-- In order to implement 'updateField', pick one of the following approaches:
8183
--
82-
-- 2. Check that the type of the 'Field' matches the 'Type' of the supplied
83-
-- 'Value' (using 'DE.testEquality').
84+
-- * Derive a 'Generic' instance for the struct data type and then define
85+
-- @'updateField' = 'updateFieldDefault'@ in the 'Struct' instance.
8486
--
85-
-- 3. If both (1) and (2) succeed, update the corresponding struct field using
86-
-- a record update.
87+
-- * Manually implement 'updateField' by doing the following for each 'Field'
88+
-- in a struct:
8789
--
88-
-- For a complete end-to-end example that demonstrates how to implement
89-
-- 'updateField' and use it in the Copilot interpreter, see the
90-
-- @examples/StructsUpdateField.hs@ example in the @copilot@ library.
90+
-- 1. Check that the name of the 'Field' matches the name of the supplied
91+
-- 'Value' (using 'GHC.TypeLits.sameSymbol').
92+
--
93+
-- 2. Check that the type of the 'Field' matches the 'Type' of the supplied
94+
-- 'Value' (using 'DE.testEquality').
95+
--
96+
-- 3. If both (1) and (2) succeed, update the corresponding struct field
97+
-- using a record update.
98+
--
99+
-- For a complete end-to-end example that demonstrates how to manually
100+
-- implement 'updateField' and use it in the Copilot interpreter, see the
101+
-- @examples/StructsUpdateField.hs@ example in the @copilot@ library.
91102
updateField :: a -> Value t -> a
92103
updateField = error $ unlines
93104
[ "Field updates not supported for this type."

0 commit comments

Comments
 (0)