Haskellで拡張無しでみそスープする
C++ では 2 + 2 の動作を上書きできないかもしれないが、ところで、ここに Haskell という言語があります
— Make 生活リズム 正常 again (@mod_poppo) 2018年1月23日
「1+1は?」
— Hideyuki Tanaka (@tanakh) 2018年1月23日
Haskell「みそスープ」 pic.twitter.com/SF9wi21zeJ
+
を実行できるようにするにはNum
のインスタンスを作れば良い.
みそスープを出力するようにするにはShow
を弄れば良い.
しかしデフォルトだと1
はInteger
に型つけられるのでみそスープにはならない.
というわけでどうやってやるのか一瞬わからなくなりました.
Haskellの1 == "x" が違法だなんて誰も言ってない! - Qiita
でRebindableSyntax
を知りましたが.
できれば拡張無しでやりたいですね.
ググったらそういうのはdefault宣言で解決できるようですね.
Haskell 98からあります.
クラス Num における曖昧性はよくあることである。それで、Haskell ではこれを解決するもうひとつの方法を提供する。 default 宣言を使う方法である。
default (t1 , ... , tn)
main = print $ 1 + 1
data M
instance Show M where
show _ = "みそスープ"
instance Num M where
default (M)
これで拡張無しでみそスープされます.
と思ったのですが,
元のみそスープはprint
ではなくてputStrLn
ですね.
putStrLn
の定義を弄れば当然可能でしょうけど,
それはレギュレーション違反とします.
putStrLn
版は拡張なしでは私の探った限りでは無理そうです.
FlexibleInstances
を使えばputStrLn
の定義を変えずにみそスープ可能です.
{-# LANGUAGE FlexibleInstances #-}
main = putStrLn $ 1 + 1
instance Num String where
_ + _ = "みそスープ"
default (String)
Prelude
のputStrLn
を使わなくて良いというレギュレーションならば拡張も無しに楽にみそスープできます.
import Prelude (($), (+))
import qualified Prelude as P
main = putStrLn $ 1 + 1
putStrLn _ = P.putStrLn "みそスープ"
と思ったら普通に出来るらしいですね. 知識が足りなかった.
Haskell で GHC 拡張なしに String 型を Num のインスタンスにするテクニックです: https://t.co/VOB5fCc6HU
— Make 生活リズム 正常 again (@mod_poppo) 2018年1月24日
そう言えば元ネタの元ネタのa == 1 && a == 2 && a == 3
は拡張無しで楽に可能です.
main = print $ a == 1 && a == 2 && a == 3
data N = N
instance Eq N where
_ == _ = True
instance Num N where
a = N