SimpleImputer converts `int32[pyarrow]` extension array to `float64`, subsequently crashing with numpy `int32` values

### Describe the bug

When using the `SimpleImputer` with a pyarrow-backed pandas DataFrame, any float/integer data is converted to `None`/`float64` instead.
This causes the imputer to be fitted to `float64`, crashing on a dtype assertion when passing it a numpy-backed `int32` DataFrame after fitting.

The flow is the following:
1. The imputer calls `_validate_input`:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/impute/_base.py#L319
2. This calls `validate_data`:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/impute/_base.py#L344-L353
3. This calls `check_array`:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/utils/validation.py#L2951-L2952
4. Our input is a pandas dataframe:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/utils/validation.py#L909
5. This now checks if the dtypes need to be converted:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/utils/validation.py#L925-L927
6. Our input is backed by an extension array _and_ `int32[pyarrow]` is an integer datatype, so we return `True` here:
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/utils/validation.py#L714-L724
7. Finally we pass the "needs conversion" check and convert the dataframe to `dtype` (which is `None` here, which apparently means `float64`):
  https://github.com/scikit-learn/scikit-learn/blob/675736ae9e3f360975e1f5b477a8eba68a376ba9/sklearn/utils/validation.py#L966-L971

### Steps/Code to Reproduce

```py
import polars as pl
from sklearn.impute import SimpleImputer
import numpy as np

print(
    SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0)
      .fit(pl.DataFrame({"a": [10]}, schema={"a": pl.Int32}).to_pandas(use_pyarrow_extension_array=False))
      ._fit_dtype
)
# prints dtype('int32'), as expected

print(
    SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0)
      .fit(pl.DataFrame({"a": [10]}, schema={"a": pl.Int32}).to_pandas(use_pyarrow_extension_array=True))
      ._fit_dtype
)
# prints dtype('float64') (!!)
```


### Expected Results

Both imputers should be fitted with `int32` values.

### Actual Results

The imputer using the pyarrow extension array is fitted with `float64`.

This causes crashes when using the Imputer with normal `int32` columns backed by numpy, as they won't be converted and therefore the dtypes differ.

### Versions

```shell
System:
    python: 3.12.9 (main, Mar 11 2025, 17:26:57) [Clang 20.1.0 ]
executable: /tmp/scikit/.venv/bin/python3
   machine: Linux-6.14.4-arch1-2-x86_64-with-glibc2.41

Python dependencies:
      sklearn: 1.6.1
          pip: None
   setuptools: None
        numpy: 2.2.5
        scipy: 1.15.3
       Cython: None
       pandas: 2.2.3
   matplotlib: None
       joblib: 1.5.0
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /tmp/scikit/.venv/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-6bb31eeb.so
        version: 0.3.28
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /tmp/scikit/.venv/lib/python3.12/site-packages/scipy.libs/libscipy_openblas-68440149.so
        version: 0.3.28
threading_layer: pthreads
   architecture: Haswell

       user_api: openmp
   internal_api: openmp
    num_threads: 16
         prefix: libgomp
       filepath: /tmp/scikit/.venv/lib/python3.12/site-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None
```

COMMENT:
The core issue stems from the fact that `pandas.api.types.is_integer_dtype` does not recognize polars (or pyarrow-backed) integer dtypes as integer types. For example:

```
from pandas.api.types import is_integer_dtype
import polars as pl
import pandas as pd

print(is_integer_dtype(int))           # True
print(is_integer_dtype(pl.Int32))      # False <--- problematic
print(is_integer_dtype(pd.Int32Dtype())) # True

```
This leads to unexpected conversion of pyarrow-backed integer columns to float64 inside check_array in scikit-learn, causing inconsistent dtype handling and eventual crashes when mixing pandas and polars dataframes or numpy arrays.

**Proposal**

I would like to work on making the `check_array` function dtype-checking logic more agnostic and robust, so that it correctly recognizes integer types from both pandas and polars (including pyarrow extension arrays). This would avoid unwanted dtype conversions and improve compatibility.

Happy to discuss the best approach and how to write tests for this.

/take

Labels: Bug, module:impute