連想リストからassoc

再帰の(ry 勉強の為なので、一連のコードは既にあるメソッドなんかも気にせず実装してます。

#Ruby配列の配列で
require "pp"
def assoc(item,dict)
  if dict.empty?
    nil
  else
    if item == dict.first.first
      dict.first
    else
      dict.shift
      assoc(item,dict)
    end
  end
end
pp assoc("Two", [["Zero",0],["One",1],["Three",3],["Two",2]])

Scala版はタプルが要素になってるListを対象としたassocとしてみた。返り値のタプルの要素の型がどれでもいいような設定の仕方が、これでいいのかちょっと自信がない。というか、始め(T,T)ってしようとしたけど、最初のifのとこの(None,None)でerror type mismatch;だったのでこうしちゃったよ。

//Scala (Any,Any)でいいのだろうか?
def assoc[T](item: T, list: List[(T,T)]): (Any,Any)={
 if (list.isEmpty) None                      
 else                                               
   if (item == list.head._1) list.head               
   else assoc(item, list.tail)                        
}
println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2)))) 
//=>("Two",2)
//Scala パターンマッチ
def assoc[T](item: T, list: List[(T,T)]): (Any,Any)=
  list match {
  case List() => (None,None)                      
  case head :: tail =>                                               
   if (item == head._1) head                
   else assoc(item, tail)                        
}
println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2)))) 
//=>("Two",2)

10/13
上のコードで(Any,Any)を返り値としてて悶々としてたんですが、id:kmizushimaさんとymnkさんから教えてもらいました! ありがとうございます。
以下、kmizushimaさんより。

Scala版の方ですが、型エラーになる理由は、見つからなかったときに
(None, None)を返そうとしているからですね。見つからなかった場合は
Noneを、見つかった場合にはSome[(K, V)]を返すようにすべきだと思います。
以下、コード例。

def assoc[A, B](item: A, list: List[(A,B)]): Option[(A, B)] = list match {
case Nil => None
case head :: tail =>
if(item == head._1) Some(head) else assoc(item, tail)
}
println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2))))
//=>Some("Two",2)

見つからないときに(None,None)ってしてたのは、見つかった時にタプルを返すので、それにあわせたような感じじゃないと返せないのかなと思ってこうしちゃったんですね。お恥ずかしい。
Option型に対する理解が一段進んだ感じ。ありがとうございました。