🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

Q&A

2回答

373閲覧

[Haskell] インスタンス宣言の書き換え

mightyMask

総合スコア143

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

0グッド

0クリップ

投稿2019/11/14 03:25

編集2019/11/14 04:38

特定の型に対して、1つのインスタンス宣言部だけを上書きして新しい型とする事は可能でしょうか。

やりたい事の具体例を2つ挙げると、

  1. なんらかの型Tに対して、instance Ord Tだけを書き換えて順序付けを変更する。

Tの他の機能はそのまま使えるようにしつつ、いちいちsortByとかを使わなくて良いようにするため。
2. instance Show (Tree a)を書き換えて、木構造を字下げ構文で表現するようにする。

追記

GeneralizedNewtypeDerivingを利用して妥協するのも良いのですが、まだ少し不便な部分があります。
引き継ぐ前のインスタンスはderivingで引き継げますが、その他は引き継げません。
例えばIntOrd以外を引き継いだとして、その他の四則演算などの関数は全て定義し直しです。
またTree aを引き継いだ場合、Eqとかは引き継げますが、Functorとかは引き継げないです。
この辺を解決するのはやはり無理ですかね?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

インスタンスを変えるには型を変える必要があります。この場合適しているのは newtype でくるむことです。

標準では deriving 句に指定できる型クラスには制限がありますが、GeneralizedNewtypeDeriving 言語拡張を有効にすることで newtype の場合にはその制限を緩めることができます。

haskell

1{-# LANGUAGE GeneralizedNewtypeDeriving #-} 2 3data A = A {} deriving (Show, Read, Eq, Ord, Bounded) 4 5class C1 a where 67 8class C2 a where 910 11instance C1 A where 1213 14instance C2 A where 1516 17newtype B = B A deriving ( Show, Read, Eq, Ord, Bounded -- これらは標準で導出できる 18 , C1 -- これは generalized newtype deriving を有効にすると導出できる 19 ) 20 21instance C2 B where -- 書き換えたいものは手動で実装する 2223

deriving に実装を変えたくない型クラスを列挙する必要がありますがこれでできます。

投稿2019/11/14 04:16

kakkun61

総合スコア285

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

1つの型の1つのインスタンスだけを書き換えて、同じ型における他のあらゆるインスタンスをそのまま利用する、ということですよね?
残念ながらできません。

ただし、 GeneralizedNewtypeDeriving GHCの言語拡張を使えば、1つの型の1つのインスタンスを書き換えつつ、同じ型における他の明示的に選ばれたインスタンスをそのまま引き継いだ、別の型を作るということはできます。

(以下のコードはGHCiに貼り付けることを想定しています。> はプロンプトです)

-- 書き換え対象となる型 > data T = T1 | T2 deriving (Eq, Ord, Show) > :{ > class SomeClass a where > someMethod :: a -> String > :} > :{ > instance SomeClass T where > someMethod _ = "I'm T!" > :} -- derivingで作られた、普通のOrdやShowのインスタンス > T1 < T2 True > T1 > T2 False > show T1 "T1" -- GeneralizedNewtypeDerivingをGHCi上で有効にするにはこう書く > :set -XGeneralizedNewtypeDeriving -- GeneralizedNewtypeDerivingを使っているおかげで、 -- TのSomeClassのインスタンスをderivingで引き継ぐことができる > newtype NewT = NewT T deriving (Eq, SomeClass) -- NewTのOrd型クラスのインスタンスのみ、 -- Tのそれと逆に振る舞うように定義できる > :{ > instance Ord NewT where > (NewT T1) <= (NewT T2) = False > _ <= _ = True > :} > NewT T1 < NewT T2 False > NewT T1 > NewT T2 True -- ただし、Show型クラスのインスタンスについてはderivingに書いていないので引き継げていない > show (NewT T1) <interactive>:39:1: error: • No instance for (Show NewT) arising from a use of ‘show’ • In the expression: show (NewT T1) In an equation for ‘it’: it = show (NewT T1)

投稿2019/11/14 04:13

igrep

総合スコア433

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問