You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Scala与Cats:数值类型转Id[T]调用sumOfSquares时Monad隐式缺失问题

Hey there! Let's dig into why you're hitting that could not find implicit value for evidence parameter of type cats.Monad[[A]Any] error when trying to use your sumOfSquares function with Id[T].

First, let's break down the root issue

That error sounds scary, but it boils down to this: the compiler can't find a Monad instance for the type it's inferring (in this case, Any), but Cats absolutely provides a Monad[Id] instance—the problem is likely in your imports, function signature, or how you're calling the function.

Step-by-step fixes

1. Make sure you're importing the right Cats utilities

First, double-check you have the necessary imports to pull in Monad[Id] and other implicit instances. Add these at the top of your file:

import cats._
import cats.implicits._

Skipping these imports is the most common reason the compiler can't find the Monad[Id] instance.

2. Fix your sumOfSquares function signature

Since Id[T] is just a type alias for T (type Id[A] = A), you don't need an explicit implicit conversion from T to Id[T]—they're the same type! A well-formed sumOfSquares that works with Id (and any other Monad) might look like this:

def sumOfSquares[F[_]: Monad, T: Numeric](values: F[T]): F[Double] = {
  val numeric = implicitly[Numeric[T]]
  // Map each value to its square, then fold to sum them
  values.map(t => numeric.toDouble(t) * numeric.toDouble(t))
    .foldLeft(0.0.pure[F]) { (acc, square) =>
      acc.flatMap(total => square.map(s => total + s))
    }
}

This version uses Numeric[T] to handle any numeric type, and Monad[F] to support Id, Option, List, etc.

3. Fix the call site to guide type inference

Your error happens at the println line because the compiler is incorrectly inferring F[_] as Any instead of Id. Fix this by either:

  • Explicitly specifying the type parameters when calling the function:
    val intSum = sumOfSquares[Id, Int](List(1, 2, 3))
    println(s"Sum of squares for int $intSum")
    
  • Or leveraging the fact that Id[T] is just T—you can pass a regular value directly (no need to wrap it in Id):
    // Since Id[List[Int]] is just List[Int]
    val intSum = sumOfSquares(List(1, 2, 3))
    println(s"Sum of squares for int $intSum")
    

Full working example

Here's a complete snippet you can test:

import cats._
import cats.implicits._

def sumOfSquares[F[_]: Monad, T: Numeric](values: F[T]): F[Double] = {
  val numeric = implicitly[Numeric[T]]
  values.map(t => numeric.toDouble(t) * numeric.toDouble(t))
    .foldLeft(0.0.pure[F]) { (acc, square) =>
      acc.flatMap(total => square.map(s => total + s))
    }
}

// Test with Id (which is just the raw type)
val intSum = sumOfSquares[Id, Int](List(1, 2, 3))
println(s"Sum of squares for int $intSum") // Output: Sum of squares for int 14.0

// Test with another Monad (like Option) to prove flexibility
val optSum = sumOfSquares(Option(5))
println(s"Sum of squares for Option: $optSum") // Output: Sum of squares for Option: Some(25.0)

内容的提问来源于stack exchange,提问作者Viswanath

火山引擎 最新活动