       ** (KeyError) key :b not found in: %{a: 1}
 
   """
-  @spec update!(map, key, (value -> value)) :: map
+  @spec update!(map, key, (current_value :: value -> new_value :: value)) :: map
   def update!(map, key, fun) when is_function(fun, 1) do
     value = fetch!(map, key)
     put(map, key, fun.(value))


  If `key` is present in `map` with value `value`, `fun` is invoked with
  argument `value` and its result is used as the new value of `key`. If `key` is
  not present in `map`, `initial` is inserted as the value of `key`. The initial
  value will not be passed through the update function.

  ## Examples

      iex> Map.update(%{a: 1}, :a, 13, fn existing_value -> existing_value * 2 end)
      %{a: 2}
      iex> Map.update(%{a: 1}, :b, 11, &(&1 * 2))
      %{a: 1, b: 11}

  """
  @spec update(map, key, value, (value -> value)) :: map
  def update(map, key, initial, fun) when is_function(fun, 1) do
    case map do
      %{^key => value} ->
        put(map, key, fun.(value))

      %{} ->
        put(map, key, initial)

      other ->
        :erlang.error({:badmap, other}, [map, key, initial, fun])
    end
  end


  end

  @doc """
  Gets the value from `key` and updates it, all in one pass. Raises if there is no `key`.

  Behaves exactly like `get_and_update/3`, but raises a `KeyError` exception if
  `key` is not present in `map`.
