是否可以为"非monad"定义实例约束,以便定义两个非重叠实例,一个用于monadic值,另一个用于非monadic值?
一个简化的例子:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverlappingInstances #-}
class WhatIs a b | a -> b where
whatIs :: a -> b
instance (Show a) => WhatIs a String where
whatIs = show
instance (Monad m, Functor m, Show a) => WhatIs (m a) (m String) where
whatIs x = fmap show x
main :: IO ()
main = do
let x = 1 :: Int …Run Code Online (Sandbox Code Playgroud) 我试图定义这个函数来重新组合三个对列表:
{-# LANGUAGE RankNTypes #-}
mapAndZip3 :: (forall x. x -> f x) -> [a] -> [b] -> [c]
-> [(f a, f b, f c)]
mapAndZip3 f la lb lc = zipWith3 (\a b c -> (f a, f b, f c)) la lb lc
main = do
let x = mapAndZip3 (fst) [(1,"fruit"), (2,"martini")]
[("chips","fish"),("rice","steak")]
[(5,"cake"),(4,"pudding")]
print x -- was expecting [(1,"chips",5), (2,"rice",4)]
Run Code Online (Sandbox Code Playgroud)
起初我没有包括RankNTypes或者forall,但是在看到这个之后,即liftTup定义,我认为它应该足够了.
但很明显,事实并非如此,因为我仍然会收到错误:
mapAndZip3.hs:8:25:
Couldn't match type `x' …Run Code Online (Sandbox Code Playgroud) 我正在尝试定义Markdown newtype,并使用GeneralizedNewtypeDeriving自动定义新实例:
import Text.Markdown
import Yesod.Text.Markdown
import Database.Persist.Sql
newtype MarkdownNewT = MarkdownNewT { getMarkdown :: Markdown }
deriving (Eq, IsString, Monoid, PersistField, PersistFieldSql)
Run Code Online (Sandbox Code Playgroud)
对于PersistFieldSql以下消息,此操作失败:
Could not coerce from ‘m Markdown’ to ‘m MarkdownNewT’
because ‘m Markdown’ and ‘m MarkdownNewT’ are different types.
arising from the coercion of the method ‘sqlType’ from type
‘forall (m :: * -> *). Monad m => m Markdown -> SqlType’ to type
‘forall (m :: * -> *). Monad m …Run Code Online (Sandbox Code Playgroud) 所以,我开始尝试quasiquotation和模板haskell.
我想修改一个现有的(大)准规则代码,同时使用在"被调用"的地方定义的变量的实际值.举一个简单的例子说明:
main.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Exp02
x = "cde"
main = do
putStrLn [str|$x|]
Run Code Online (Sandbox Code Playgroud)
Exp02.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Exp02 where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
xpto :: String -> ExpQ
xpto [] = stringE []
xpto ('$':rest) = varE (mkName rest)
xpto str = stringE str
str = QuasiQuoter
{ quoteExp = xpto
, quotePat = fail $ "patterns"
, quoteType= fail $ "types" …Run Code Online (Sandbox Code Playgroud)