有:
getSdr = Sdr <$> u1 <*> u1 <*> u1 <*> getU1List <*> mcn <*> mcn␣
<*> mcn <*> mcn <*> mcn <*> mcn <*> mcn <*> mcn <*> mcn
<*> mcn <*> mcn <*> mcn <*> mcn <*> mcn <*> mcn <*> mcn
想要:
getSdr = Sdr <$> u1 <*> u1 <*> u1 <*> getU1List <*> replicateA 16 mcn
我确实注意到replicateA
中的Data.Sequence
,但我不知道该图书馆,或者它是否可以在这里提供帮助。它不会进行类型检查,因为它是
replicateA :: Applicative f => Int -> f a -> f (Seq a)
似乎没有逃脱Seq
澄清一下,Sdr是一个记录:
| Sdr { sdrHeadNum :: !U1
, sdrSiteGrp :: !U1
-- , siteCount :: !U1
, siteNums :: [U1]
, handlerType :: Maybe Text
, handlerId :: Maybe Text
, probeCardType :: Maybe Text
, probeCardId :: Maybe Text
, loadBoardType :: Maybe Text
, loadBoardId :: Maybe Text
, dibType :: Maybe Text
, dibId :: Maybe Text
, cableType :: Maybe Text
, cableId :: Maybe Text
, contactorType :: Maybe Text
, contactorId :: Maybe Text
, laserType :: Maybe Text
, laserId :: Maybe Text
, extraType :: Maybe Text
, extraId :: Maybe Text }
它是所有数据类型的母亲的一部分:https://github.com/gitfoxi/Stdf/blob/WIP/Data/Stdf/Types.hs
答案 0 :(得分:6)
这个答案需要疯狂的笑声。我不打算输出那部分;你只需要想象。
在惯用的Haskell中你想要的是不可能的。你想要的可能是一个坏主意。但你想要的并不是完全不可能的。
第一个警告标志:我们需要大量的编译器扩展。我想,只有最后一个不是严格要求的。 (这整个答案假设GHC 7.8;我认为它可以调整为7.6。)
{-# LANGUAGE TypeFamilies, DataKinds, MultiParamTypeClasses,
FlexibleInstances, ScopedTypeVariables, NoMonomorphismRestriction #-}
module Maniacal where
import Control.Applicative
import Data.Proxy
以疯狂的方式,我会先说清楚:
getSdr :: Applicative f => f Sdr
getSdr = Sdr <$> u1 <*> u1 <*> u1 <*> getU1List # starN sixteen mcn
ghci> getSdr :: [Sdr]
[Sdr A A A B C C C C C C C C C C C C C C C C]
ghci> :type starN sixteen mcn
{- something hideous -}
但是怎么样?! (顺便说一句,Sdr
等的样板定义位于最底层。)
首先,我们需要一个类型级别16,我们可以在递归类型类中使用它。 (GHC的花式类型数字不支持7.8的归纳,在这里没用。)
data PInt = One | S PInt -- Promoted to types
type Sixteen = S (S (S (S (S (S (S (S (S (S (S (S (S (S (S One))))))))))))))
sixteen :: Proxy Sixteen
sixteen = Proxy
在大锅里我们扔了一个疯狂的类型。
class MultiStar (n :: PInt) a b where
type MultiStarT n a b :: *
starN :: Applicative f => proxy n -> f a -> f (MultiStarT n a b) -> f b
instance MultiStar One a b where
type MultiStarT One a b = a -> b
starN _ v f = f <*> v
instance (MultiStar n a b, (MultiStarT n a b) ~ (a -> t0))
=> MultiStar (S n) a b where
type MultiStarT (S n) a b = a -> MultiStarT n a b
starN _ v f = starN (Proxy :: Proxy n) v (addOne <$> f)
where addOne g x = g x x
不要问我约束中的相等性。
最后,有点语法精神:
(#) = flip ($)
infixl 4 #
我们已经完成了!现在只是样板。 (或者它应该是釜板吗?)和疯狂的笑声。
data A = A deriving Show
data B = B deriving Show
data C = C deriving Show
data Sdr = Sdr A A A B C C C C C C C C C C C C C C C C deriving Show
u1 = pure A
getU1List = pure B
mcn = pure C
答案 1 :(得分:2)
我不认为你想要的是可能的。添加parens并简化:
getSdr = (((Sdr <$> u1) <*> u1) <*> u1) -- ...
这些运算符组在左侧(infixl)和&lt; *&gt;不是关联的,所以你不能只替换右手边。
即使你可以,这种类型是什么?让我们说:
data Sdr = Sdr Int Int Char Char Char
u1 :: Parser Int
mcn :: Parser Char
getSdr :: Parser Sdr
getSdr = Sdr <$> u1 <*> u1 <*> mcn <*> mcn <*> mcn
您希望用以下内容替换mcn部分:
getSdr = Sdr <$> u1 <*> u1 <*> mcn3
但第一部分的类型是:
Sdr <$> u1 <*> u1 :: Parser (Char -> Char -> Char -> Sdr)
您无法使用&lt; *&gt;将其应用于获得Parser Sdr的东西。
答案 2 :(得分:2)
您可以使用
制作replicateA
功能
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
它允许您通过Traversable传递Applicative仿函数。
(差不多,Traversable意味着sequenceA
有效。[]
肯定是可以穿越的。)
import Data.Traversable (sequenceA)
replicateA :: Applicative f => Int -> f a -> f [a]
replicateA n x = sequenceA (replicate n x)
这意味着您可以(例如)replicateA 16 mcn :: Get [Text]
,但它不能使用您的数据构造函数。你可能需要选择重写你的构造函数或放弃replicateA
,我担心。