gpt4 book ai didi

haskell - 使用 SYB 和 ad-hoc 多态性在 Haskell 中进行泛型编程

转载 作者:行者123 更新时间:2023-12-04 13:19:32 24 4
gpt4 key购买 nike

我有一个与 Show 相同的类(class)我想为每个元组类型创建一个此类的实例。通常这是通过为每个元组类型单独编写实例来完成的

instance  (Show a, Show b) => Show (a,b)  where
showsPrec _ (a,b) s = show_tuple [shows a, shows b] s

instance (Show a, Show b, Show c) => Show (a, b, c) where
showsPrec _ (a,b,c) s = show_tuple [shows a, shows b, shows c] s

instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
showsPrec _ (a,b,c,d) s = show_tuple [shows a, shows b, shows c, shows d] s
...

为每个元组类型编写一个实例会产生大量样板文件,并且很容易看到所有 showPrec 之间共享的通用模式。实现。为了避免这种样板,我想我可以使用 Data.Generics来自 Scrap your boilerplate并实现一个折叠元组,比如
showTuple = intercalate " " . gmapQ ("" `mkQ` show)

但是 showTuple由于某种原因不起作用
> showTuple (1,2)
" "

我认为问题在于 show是多态的,因为如果我专门 showTuple然后它工作
showTupleInt = intercalate " " . gmapQ ("" `mkQ` (show :: Int -> String))
> showTupleInt (1::Int,2::Int)
"1 2"

我检查了 gshow的代码这与我需要的类似,但我不知道它是如何工作的。如果我尝试将其代码导入 GHCI,则会收到错误消息:
> let gshows = (\t -> showChar '('
. (showString . showConstr . toConstr $ t)
. (foldr (.) id . gmapQ ((showChar ' ' .) . gshows) $ t)
. showChar ')'
) `extQ` (shows :: String -> ShowS)
<interactive>:262:59:
Could not deduce (a ~ d)
from the context (Data a)
bound by the inferred type of
gshows :: Data a => a -> String -> String
at <interactive>:(259,5)-(264,44)
or from (Data d)
bound by a type expected by the context:
Data d => d -> String -> String
at <interactive>:262:33-65
`a' is a rigid type variable bound by
the inferred type of gshows :: Data a => a -> String -> String
at <interactive>:259:5
`d' is a rigid type variable bound by
a type expected by the context: Data d => d -> String -> String
at <interactive>:262:33
Expected type: d -> String -> String
Actual type: a -> String -> String
In the second argument of `(.)', namely `gshows'
In the first argument of `gmapQ', namely
`((showChar ' ' .) . gshows)'
In the second argument of `(.)', namely
`gmapQ ((showChar ' ' .) . gshows)'

所以我有两个问题:
  • showTuple 有什么问题|以及如何修复它以使其适用于任何大小的元组
  • 如何gshow有效,为什么如果我在 GHCI 上导入其代码会出现该错误?

  • 编辑:我在学习 Data.Generics和一般的SYM,所以我想使用那个模块。只有当它仅使用该模块时,我才会接受答案。谢谢。

    最佳答案

    我更熟悉 GHC Generics,而不是 SYB,所以我提供了一个基于 Generics 的解决方案。虽然它不能直接回答您的问题,但我希望它也有用。

    {-# LANGUAGE TypeOperators, FlexibleContexts, DefaultSignatures #-}
    import Data.Sequence
    import GHC.Generics

    class Strs' f where
    strings' :: f a -> Seq String

    instance Strs' U1 where
    strings' U1 = empty

    instance Show c => Strs' (K1 i c) where
    strings' (K1 a) = singleton $ show a

    instance (Strs' a) => Strs' (M1 i c a) where
    strings' (M1 a) = strings' a

    instance (Strs' f, Strs' g) => Strs' (f :*: g) where
    strings' (a :*: b) = strings' a >< strings' b

    class Strs a where
    strings :: a -> Seq String
    default strings :: (Generic a, Strs' (Rep a)) => a -> Seq String
    strings = strings' . from

    -- Since tuples have Generic instances, they're automatically derived using
    -- the above default.
    instance Strs () where
    instance (Show a, Show b) => Strs (a, b) where
    instance (Show a, Show b, Show c) => Strs (a, b, c) where

    关于haskell - 使用 SYB 和 ad-hoc 多态性在 Haskell 中进行泛型编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20806157/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com