0

私はscalazLearn You A Haskell For Greater Good の学習に取り組んでおり、filterM の例を LYAHFGG から Scala に変換する方法を考えています。

fst $ runWriter $ filterM keepSmall [9,1,5,2,10,3]

としてkeepSmall定義された

keepSmall :: Int -> Writer [String] Bool  
keepSmall x  
    | x < 4 = do  
        tell ["Keeping " ++ show x]  
        return True  
    | otherwise = do  
        tell [show x ++ " is too large, throwing it away"]  
        return False

私の素朴なアプローチはコンパイルエラーで終わり、その問題を回避する方法がわかりません!

    val keepSmall: (Int => WriterT[Id, Vector[String], Boolean]) = (x: Int) => 
      if (x < 4) for {
        _ <- Vector("Keeping " + x.shows).tell
      } yield true
      else for {
        _ <- Vector(x.shows + " is too large, throwing it away").tell
      } yield false

println(List(9,1,5,2,10,3) filterM keepSmall)

コンパイル エラー:

 Error:(182, 32) no type parameters for method filterM: (p: Int => M[Boolean])(implicit evidence$4: scalaz.Applicative[M])M[List[Int]] exist so that it can be applied to arguments (Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean]
 required: Int => ?M[Boolean]
    println(List(9,1,5,2,10,3) filterM keepSmall)
                               ^

Error:(182, 40) type mismatch;
 found   : Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean]
 required: Int => M[Boolean]
    println(List(9,1,5,2,10,3) filterM keepSmall)
                                       ^
4

1 に答える 1

2

この問題は、Scalaがで期待される引数に 3 つのを持つ型を適合させる方法を本当に認識できないという事実によるものfilterMです。Boolean

次のような奇妙な型ラムダ構文を使用して問題を解決できます (テストされていないため、機能しない可能性があります)。

val keepSmall: (Int => ({type L[T] = WriterT[Id, Vector[String], T]})#L) = ...

または (はるかに簡単に) 次のように型エイリアスを導入します。

type MyWriter[T] = WriterT[Id, Vector[String], T]
val keepSmall: (Int => MyWriter[Boolean]) = ...

これにより、 によって期待される引数の種類が、指定しfilterMた引数の種類と一致することが保証されます。

于 2015-09-21T10:39:58.590 に答える