はい、なので実際のコードでは
実際のところは正確にわからないので本当は
Word64 にしています。実際のところは正確にわからないので本当は
Integer のほうがいいのかもしれませんが。Word64 にしています。Integer のほうがいいのかもしれませんが。universum を使ってみたんですけど、第一印象は「かゆいところに手が届かない」Preludeでした。type SomeMap = Map String int import Data.Map.Strictができないんです。3.2 Fold は確かに Parametricity と代数の可換性から自然に fusion が導かれているのが分かりました 重ねてご教示有難うございましたtype family ConsUnless (b :: Bool) (x :: k) (xs :: [k]) :: [k] where ConsUnless False x xs = (x ': xs) ConsUnless True _ xs = xs type family Reject (p :: (k -> Bool)) (xs :: [k]) :: [k] where Reject p '[] = '[] Reject p (x ': xs) = ConsUnless (p x) x (Reject p xs) type family Same (x :: k) (y :: k) :: Bool where Same x x = 'True Same x y = 'False type family Without (x :: k) (xs :: [k]) :: [k] where Without x xs = Reject (Same x) xs
• The type family ‘Same’ should have 2 arguments, but has been given 1
• In the equations for closed type family ‘Without’
In the type family declaration for ‘Without’
Same が2つ引数をとるのはいいとして、 Reject の第一引数が引数を1つとる型族をとるよう宣言しているので、 Same x とすればいいんじゃないかと思えるのですが、なんでエラーになってしまうのでしょうか?Remove に相当するのは Without と呼んでいます。
type family Result (x :: k) (xs :: [k]) :: [k] where
Result x '[] = '[]
Result x (x ': xs) = Result x xs
Result x (y ': ys) = y ': Result x ys
class Without (x :: k) (xs :: [k]) where
without :: Membership xs x -> (h :* xs) -> (h :* Result x xs)
instance Without x '[] where
without _ _ = nil
instance Without x (x ': xs) where
without key rec =
let (_, ys) = huncons $ toHList rec
in without key (fromHList ys)
instance Without x (y ': ys) where
without key rec =
let (y, ys) = huncons $ toHList rec
in y <: without key (fromHList ys)
huncons :: HList h (x ': xs) -> (h x, HList h xs)
huncons (HCons hx hxs) = (hx, hxs)
app\Main.hs:41:21: error:
? Couldn't match type ‘xs’ with ‘x : xs’
‘xs’ is a rigid type variable bound by
the instance declaration at app\Main.hs:38:10-28
Expected type: h :* (x : xs)
Actual type: h :* xs
? In the second argument of ‘without’, namely ‘(fromHList ys)’
In the expression: without key (fromHList ys)
In the expression:
let (_, ys) = huncons $ toHList rec in without key (fromHList ys)
? Relevant bindings include
ys :: HList h xs (bound at app\Main.hs:40:13)
rec :: h :* (x : xs) (bound at app\Main.hs:39:15)
key :: Membership (x : xs) x (bound at app\Main.hs:39:11)
without :: Membership (x : xs) x
-> (h :* (x : xs)) -> h :* Result x (x : xs)
(bound at app\Main.hs:39:3)
|
41 | in without key (fromHList ys)
| ^^^^^^^^^^^^
app\Main.hs:46:26: error:
? Couldn't match type ‘ys’ with ‘y : ys’
‘ys’ is a rigid type variable bound by
the instance declaration at app\Main.hs:43:10-28
Expected type: h :* (y : ys)
Actual type: h :* ys
? In the second argument of ‘without’, namely ‘(fromHList ys)’
In the second argument of ‘(<:)’, namely
‘without key (fromHList ys)’
In the expression: y <: without key (fromHList ys)
? Relevant bindings include
y :: h y (bound at app\Main.hs:45:10)
ys :: HList h ys (bound at app\Main.hs:45:13)
rec :: h :* (y : ys) (bound at app\Main.hs:44:15)
key :: Membership (y : ys) x (bound at app\Main.hs:44:11)
without :: Membership (y : ys) x
-> (h :* (y : ys)) -> h :* Result x (y : ys)
(bound at app\Main.hs:44:3)
|
46 | in y <: without key (fromHList ys)
newtype Cell = Cell (Maybe Int)
newtype とすることで、 Cell はまさにおっしゃるような、 「 Maybe Int と ほとんど同じなんだけど、ほんの少し振る舞いが異なる型」として定義できます。Show はあくまでもデバッグ用の文字列に変換するものとして使ったほうがよいのではないかと考えています。newtype でセル専用の型を用意するにせよしないにせよ、Show や Read のインスタンスを無理に書き換えずに、文字列からパースして作成したり文字列に変換する用の関数は独立して作った方がいいんじゃないかと思います。instance Without x ys => Without x (y:ys) where
type family Result (x :: k) (xs :: [k]) :: [k] where Result x '[] = '[] Result x (x ': xs) = Result x xs Result x (y ': ys) = y ': Result x ys
ただ、個人的には `Show` はあくまでもデバッグ用の文字列に変換するものとして使ったほうがよいのではないかと考えています。
String の show 関数は、受け取った文字列をそのまま返すのではなく、Show のインスタンスは、traceShowId など Show のインスタンスをデバッグ用に使う関数に渡して表示させた際、(特に何カ所も出力させた場合に)どの型の値を出力したのか区別できるようにした方が、視認性が上がるためでしょう。Read のインスタンスにする必要はないだろうな、と思って触れてませんでした。