我一直在努力尝试在Development.Shake.cmd
的行上编写多arar函数,但是即使经过3天8次不同的尝试,我仍然无法对此进行编译。
这是我设法完成的事情:
{-# LANGUAGE ExtendedDefaultRules #-}
--
-- this is for an i18n system integrated with Lucid
-- where I want the `t_` function to work with a variable number of arguments
--
module Try4 where
import Lucid (HtmlT, div_, toHtmlRaw)
import Control.Monad.Trans (lift)
import Data.Text as T
default (Text)
newtype Translation = Translation { rawTranslation :: Text }
class (Monad m) => HasI18n m where
fetchTranslation :: Text -> m Translation
class (HasI18n m) => InterpolationValue m a where
-- the reason why this function is not pure, is because it is possible
-- for the conversion function to depend on the monadic context. For example,
-- it is not necessary that date/time values are always converted to text using
-- the same format. The format to be used could be part of the monadic context.
interpolationVal :: a -> m Text
class Interpolate arg result where
t_ :: arg -> result
instance (HasI18n m, a ~ ()) => Interpolate Text (HtmlT m a) where
t_ k = do
x <- lift $ fetchTranslation k
toHtmlRaw $ rawTranslation x
instance (HasI18n m, InterpolationValue m v, a ~ ()) => (Interpolate Text ((Text, v) -> HtmlT m a)) where
t_ k (i, v) = do
x <- lift $ fetchTranslation k
val <- lift $ interpolationVal v
toHtmlRaw $ applySingleInterpolation (rawTranslation x) (i, val)
instance (HasI18n m) => InterpolationValue m Text where
interpolationVal = pure
instance (HasI18n m) => InterpolationValue m Int where
interpolationVal = pure . T.pack . show
applySingleInterpolation :: Text -> (Text, Text) -> Text
applySingleInterpolation memo (k, v) = T.replace ("%{" <> k <> "}") v memo
myHtml :: (HasI18n m) => HtmlT m ()
myHtml = div_ $ do
div_ $ t_ "some.i18n.key"
div_ $ t_ "some.18n.key" ("interpolation1", "some-string")
最后,这就是我遇到的问题。如何编写(递归)类型类实例以使以下内容得以编译?无论我做什么,我都无法统一m
和InterpolationValue m a
中的HtmlT m a
。不知何故,由于Interpolate arg result
,GHC似乎感到困惑,并推断出不同的m1
和m2
。
t_ "some.18n.key"
("interpoliation1", "some-string")
("interpolation2", 10 :: Int)
("interpolation3", fromGregorian 2020 1 1)
答案 0 :(得分:0)
我建议从复制Text.Printf开始,并逐步对其进行修改,直到获得所需的内容。那是从中复制Shake版本的纯净来源。重要的实例是:
instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where
instance (a ~ ()) => PrintfType (IO a) where
那是一个归纳实例,一个终端实例。