質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Haskell

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

Q&A

解決済

2回答

325閲覧

[Haskell] Monoid Either

mightyMask

総合スコア143

Haskell

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

0グッド

0クリップ

投稿2019/12/04 05:38

編集2019/12/04 07:43

ghci

1Prelude> Just "Hoge" <> Just "Fuga" 2Just "HogeFuga" 3Prelude> Right "Hoge" <> Right "Fuga" 4Right "Hoge"

Either<>演算をMaybeと同じように使いたいのですが、何か解決策はありますでしょうか?
Haskellは技巧的な方法でいろいろ解決できると感じているので、なにか出来そうではありますが。

余談

EitherはMaybeの一般化ですので、それをコードで表してる方が綺麗な感じがします。
個人的には以下のコードみたいな感じであってほしいです。
ユニット型がMonoidであるという性質も生かせていて、綺麗だと思うのです。

Haskell

1-- import Prelude hiding (Either, Left, Right, Maybe) 2 3data Either l r = Left l | Right r 4type Maybe a = Either () a 5 6instance (Semigroup l, Semigroup r) => Semigroup (Either l r) where 7 Right x <> Right y = Right $ x <> y 8 Right x <> Left _ = Right x 9 Left _ <> Right y = Right y 10 Left x <> Left y = Left $ x <> y 11 12instance (Monoid l, Semigroup r) => Monoid (Either l r) where 13 mempty = Left mempty 14

具体的には、Eitherに対して定義されている(|||)rightといった関数をMaybeにもそのまま流用できたりします。
この場合はfromMaybefmapで充分ではありますが、他に良い例が思いつきませんでした。
これをそのまま使えば良いじゃんって思うかもしれませんが、そうすると他のライブラリと整合性がつかなくて不便です。

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

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

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

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

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

guest

回答2

0

別のインスタンスを選択する手法としては newtype でくるむのが面倒ですが正攻法です。

haskell

1newtype AppendableEither l r = AppendableEither (Either l r) 2 3instance (Semigroup l, Semigroup r) => Semigroup (AppendableEither l r) where 4

Either のデフォルトの Semigroup インスタンスがなぜ現在のものが選択されたのかは私は知りません(当時は Monoid としてですが)。
lr に制約を必要としないため、より一般的だからかもしれません。

投稿2019/12/04 08:32

kakkun61

総合スコア285

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

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

0

ベストアンサー

こんにちは。

質問文を読む限りでは「Maybe は Either と同じ挙動であってほしい」と「Either は Maybe と同じ挙動であってほしい」が混ざっていて、どっちを求めているのかが分かりませんでした。

前者については First モノイド を使えば良いと思います。

後者については、自分で定義を書いてみれば分かりますが、なんだか微妙なインスタンス定義しか書けないのであんまりオススメしません。

haskell

1data MyEither a b = MyL a | MyR b 2 3instance (???) => Semigroup (MyEither a b) where 4 ???

投稿2019/12/04 06:43

tamoto

総合スコア4105

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

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

mightyMask

2019/12/04 07:45

質問文を大幅に修正しました。 私が求めているのは後者です。 インスタンス定義はこれではダメでしょうか?
tamoto

2019/12/04 09:21 編集

個人的には LR の両方に Semigroup 制約を要求されるのが微妙ですね。 ちょっと考えてみましたが、自分だったらインスタンスは定義せず以下のようにしてしまうと思います。 foldr1 (liftA2 (<>)) [ e1, e2, e3 ] Left の合成は行わず、最初の Left を返す方が自然に見えます。 --- liftA2 の存在を思い出したので例を書き直しました。
tamoto

2019/12/04 10:02

すみません。前コメントの例は、Maybe の例で言う「Nothing を取り除いた全てを結合した結果を返す」とはなっていませんでした。 Data.Either を見ていたら、rights :: [Either a b] -> [b] という関数があることを今知ったので、Left のことは無視して fold . rights でいい気がします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問