{- |
Module      : Language.Egison.Type.Instance
Licence     : MIT

This module provides utilities for matching type class instances.
-}

module Language.Egison.Type.Instance
  ( findMatchingInstanceForType
  ) where

import           Language.Egison.Type.Types (Type(..), TyVar(..), InstanceInfo(..), freeTyVars)
import           Language.Egison.Type.Unify (unifyStrict)

-- | Find a matching instance for a given target type
-- This searches through a list of instances and returns the first one that unifies with the target type
-- Used by both type inference (Infer.hs) and type class expansion (TypeClassExpand.hs)
-- IMPORTANT: Uses unifyStrict to ensure Tensor a does NOT unify with a
-- This prevents incorrectly matching scalar instances as tensor instances
findMatchingInstanceForType :: Type -> [InstanceInfo] -> Maybe InstanceInfo
findMatchingInstanceForType :: Type -> [InstanceInfo] -> Maybe InstanceInfo
findMatchingInstanceForType Type
targetType [InstanceInfo]
instances = [InstanceInfo] -> Maybe InstanceInfo
go [InstanceInfo]
instances
  where
    go :: [InstanceInfo] -> Maybe InstanceInfo
go [] = Maybe InstanceInfo
forall a. Maybe a
Nothing
    go (InstanceInfo
inst:[InstanceInfo]
rest) =
      -- Try to unify the instance type with the target type using strict unification
      case Type -> Type -> Either UnifyError Subst
unifyStrict (InstanceInfo -> Type
instType InstanceInfo
inst) Type
targetType of
        Right Subst
_ -> InstanceInfo -> Maybe InstanceInfo
forall a. a -> Maybe a
Just InstanceInfo
inst  -- Successfully unified
        Left UnifyError
_  -> [InstanceInfo] -> Maybe InstanceInfo
go [InstanceInfo]
rest    -- Unification failed, try next instance