LoginSignup
9
8

More than 5 years have passed since last update.

Haskellの型クラスとF#のインターフェース

Last updated at Posted at 2014-08-25

Haskellの実験メモです。

Haskellの型クラスはオブジェクト指向言語のインターフェースと似ている面があります。特にF#のインターフェースは書式まで似ているため比較してみます。ただし似ているのは定義だけで、実装や呼び出し方法はあまり似ていません。

定義

書式がとても似ています。

Haskell
class Foo a where
    foo :: a -> String
F#
type Foo<'a> =
    abstract foo: 'a -> string

実装

Haskellの型クラスは、対象となる型とは分離した形で型クラスのインスタンスを作成します。

Haskell
instance (Num a, Eq a) => Foo a where
    foo 1 = "bar"
    foo _ = "?"

instance Foo String where
    foo "1" = "baz"
    foo _   = "?"

F#はあくまでオブジェクト指向的な意味合いでのインターフェースなので、クラスを定義して実装します。

F#
type FooInt() =
    interface Foo<int> with
        member x.foo a =
            match a with
            | 1 -> "bar"
            | _ -> "?"

type FooString() =
    interface Foo<string> with
        member x.foo a =
            match a with
            | "1" -> "baz"
            | _   -> "?"

呼び出し

Haskellの型クラスの関数はそのまま呼び出せます。

Haskell
main = do
    putStrLn $ foo 1
    putStrLn $ foo "1"

F#ではクラスのインスタンスを作成して、インターフェースにキャストして呼び出します。

F#
printfn "%s" <| (FooInt   () :> Foo<int>   ).foo 1
printfn "%s" <| (FooString() :> Foo<string>).foo "1"

そもそも概念が異なるので、同列に比較するのは無理があります。

メソッドのオーバーロード

F#ではメソッドのオーバーロードが可能です。今回の例ではこちらを使った方が簡単です。

F#
type Foo =
    static member foo a =
        match a with
        | 1 -> "bar"
        | _ -> "?"

    static member foo a =
        match a with
        | "1" -> "baz"
        | _   -> "?"

printfn "%s" <| Foo.foo 1
printfn "%s" <| Foo.foo "1"

F#では型クラスに相当するものはありませんが、必要に応じてインターフェースかオーバーロードを使い分けることになりそうです。

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8