ron*_*ron 7 haskell ghc-generics
如果我们有
data Foo = Foo { x :: Maybe Int, y :: Maybe Text }
Run Code Online (Sandbox Code Playgroud)
我们已经可以在Applicative上下文(这里是IO)中将它构建为applicative-style
myfoo :: IO Foo
myfoo = Foo <$> getEnvInt "someX" <*> getEnvText "someY"
Run Code Online (Sandbox Code Playgroud)
如果一个人喜欢明确地写出记录字段名称,那该怎么办?如:
myfoo = Foo { x = getEnvInt "someX", y = getEnvText "someY" }
Run Code Online (Sandbox Code Playgroud)
这不会发生变形.一个解决方案是
{-# LANGUAGE RecordWildCards #-}
myfoo = do
x <- getEnvInt "someX"
y <- getEnvText "someY"
return $ Foo {..}
Run Code Online (Sandbox Code Playgroud)
哪个不错.但我想知道(此时只为了它自己)以下是否可行:
data FooC f = FooC { x :: f Int, y :: f Text }
type Foo = FooC Maybe
myfoo :: IO Foo
myfoo = genericsMagic $ FooC
{ x = someEnvInt "someX"
, y = someEnvText "someY"
}
Run Code Online (Sandbox Code Playgroud)
我相信它可以通过裸GHC.Generics模式匹配来完成,但这样就不具备类型安全性,所以我一直在寻找更强大的方法.我遇到了generics-sop,它将记录转换为异构列表,并带来了一个看似方便的hsequence操作.
generics-sop将Applicative的类型存储在其异构列表的单独类型参数中,并且I在使用生成的转换时始终(标识).所以我需要映射hlist并I从有效移动Applicative的元素中移除所I提到的类型参数(它会Comp IO Maybe),所以我可以使用hsequence,最后添加回来I让我可以转回记录.
但我不知道如何为I删除/添加功能编写类型签名,该功能通过丢失/获取外部类型来传达各个hlist元素的类型一致地改变.这甚至可能吗?
但我不知道如何为 I 删除/添加函数编写类型签名,该签名表示各个 hlist 元素的类型通过丢失/获得外部类型来一致更改。这可能吗?
我也不知道该怎么做。一种可能的解决方法(以一些样板为代价)是使用记录模式同义词直接构造乘积和表示,同时仍然能够使用命名字段:
{-# language DeriveGeneric #-}
{-# language TypeFamilies #-}
{-# language TypeOperators #-}
{-# language PatternSynonyms #-}
import Data.Text
import qualified GHC.Generics as GHC
import Generics.SOP
import Text.Read
data Foo = Foo { x :: Int, y :: Text } deriving (Show, GHC.Generic)
instance Generic Foo
pattern Foo' :: t Int -> t Text -> SOP t (Code Foo)
pattern Foo' {x', y'} = SOP (Z (x' :* y' :* Nil))
readFooMaybe :: SOP (IO :.: Maybe) (Code Foo)
readFooMaybe = Foo'
{
x' = Comp (fmap readMaybe getLine)
, y' = Comp (fmap readMaybe getLine)
}
Run Code Online (Sandbox Code Playgroud)
在 ghci 上测试:
ghci> hsequence' readFooMaybe >>= print
12
"foo"
SOP (Z (Just 12 :* (Just "foo" :* Nil)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |