我想知道,Haskell中的自然转变是什么。自然转换用以下签名描述:
F[a] ~> G[a]
Run Code Online (Sandbox Code Playgroud)
例如,我可以转换:
Maybe a ~> List a
Run Code Online (Sandbox Code Playgroud)
对?
那怎么IO做是不可能的呢?
自然转型的目的是什么?
自然转换,而无需深入了解其背后的类别理论,实际上只是一个多态函数。
Prelude> :set -XRankNTypes
Prelude> :set -XTypeOperators
Prelude> type (~>) f g = forall x. f x -> g x
Run Code Online (Sandbox Code Playgroud)
该~>操作映射类型构造为另一种类型的构造,在这样一种方式,它适用于任何给定参数的第一类构造函数。TypeOperator扩展名是我们可以使用的扩展名,~>而不是NatTrans; 该RankNTypes是什么让我们使用forall的定义,以便调用者可以选择哪种类型的f和g将被应用到。
这里是从天然变换的例子Maybe来List,需要一个Maybe a用于任何类型的a,并产生一个等效列表(通过返回一个空列表或包裹值作为单列表)。
Prelude> :{
Prelude| m2l :: Maybe ~> []
Prelude| m2l Nothing = []
Prelude| m2l (Just x) = [x]
Prelude| :}
Prelude> m2l Nothing
[]
Prelude> m2l (Just 3)
[3]
Prelude> m2l (Just 'c')
"c"
Run Code Online (Sandbox Code Playgroud)
l2m :: [] ~> Maybe与l2m [] = Nothing和的“逆”将是l2m (x:_) = Just x。(我将引号取反,因为m2l (l2m [1,2,3]) /= [1,2,3])
没有什么可以阻止您IO用作任何一种类型构造函数(尽管如果IO在左侧,则它也必须在右侧)。
foo :: IO ~> IO
foo a = putStrLn "hi" >> a
Run Code Online (Sandbox Code Playgroud)
然后
> foo (putStrLn "foo")
hi
foo
> foo (return 3)
hi
3
Run Code Online (Sandbox Code Playgroud)
另一个示例将length视为从[]到的自然转变Const Int(改编自https://bartoszmilewski.com/2015/04/07/natural-transformations/,我强烈建议阅读):
-- Isomorphic to builtin length, as Const Int is isomorphic to Int
-- Requires importing Data.Functor.Const
length' :: [] ~> Const Int
length' [] = Const 0
length' (x:xs) = Const (1 + getConst (length' xs))
Run Code Online (Sandbox Code Playgroud)
在这里明确是有用的:自然转换是签名的函数
? :: ? a . ? a -> ? a
Run Code Online (Sandbox Code Playgroud)
where?和?是函子。的?当然是在Haskell暗示的,但是这确实是关于自然变换的关键的东西。那和交换图
即在 Haskell 中,
(fmap f :: ? x -> ? y) . (? :: ? x -> ? x)
? (? :: ? y -> ? y) . (fmap f :: ? x -> ? y)
Run Code Online (Sandbox Code Playgroud)
或简称,fmap f . ? ? ? . fmap f。(但请注意,两者?在这里都有不同的类型!)
例如,我可以转换:
也许一个 ~> 列出一个
嗯,yyyea...ish。再次,明确你的意思。具体来说,以下是从Maybeto的自然转换[](这不是从Maybe ato的自然转换[a],这是没有意义的):
maybeToList :: Maybe a -> [a]
maybeToList Nothing = []
maybeToList (Just a) = [a]
Run Code Online (Sandbox Code Playgroud)
但这并不是唯一的这种转变。事实上有?许多这样的转换,例如
maybeToList9 :: Maybe a -> [a]
maybeToList9 Nothing = []
maybeToList9 (Just a) = [a,a,a,a,a,a,a,a,a]
Run Code Online (Sandbox Code Playgroud)
怎么样
IO,自然转化是不可能的吧?
这也是可能的。例如,这是从NonEmpty到的自然转换IO:
import qualified Data.List.NonEmpty as NE
import System.Exit (die)
selectElem :: NonEmpty a -> IO a
selectElem l = do
let len = NE.length l
putStrLn $ "Which element? (Must be <"++show len++")"
i <- readLine
if i<len then die "Index too big!"
else return $ l NE.! i
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |