我尝试使用此库访问IP:
http://jacob.stanley.io/2010/08/12/ip-addresses-and-mac-addresses-in-haskell/
src:
import Network.Info
main = do
ns <- getNetworkInterfaces
mapM_ (putStr . showInterface) ns
showInterface n = name n ++ "\n"
++ " IPv4: " ++ show (ipv4 n) ++ "\n"
++ " IPv6: " ++ show (ipv6 n) ++ "\n"
++ " MAC: " ++ show (mac n) ++ "\n"
如何通过var?
中的ghci访问IPv4地址类似的东西:
let ipv4 = filterIpV4Address(ns)
ns
的类型为ns :: [NetworkInterface]
,包含所有网络接口。我是Haskell的新手,并不理解这段代码。
变量&#34; n&#34;在行showInterface n = name n ++ "\n"
是否以某种方式设置在mapM_ (putStr . showInterface) ns
行?
更新:
Prelude Network.Info Main> ns <- getNetworkInterfaces
Prelude Network.Info Main> ns
[NetworkInterface {name = "Local Area Connection", ipv4 = 169.254.166.181, ipv6
= fe80:0:0:0:94d4:87b2:7435:a6b5, mac = e8:11:32:d4:bf:04},NetworkInterface {nam
e = "Wireless Network Connection", ipv4 = 192.168.1.12, ipv6 = fe80:0:0:0:b593:3
47d:11d0:916f, mac = 00:1b:b1:28:a7:96},NetworkInterface {name = "Bluetooth Netw
ork Connection", ipv4 = 169.254.131.172, ipv6 = fe80:0:0:0:6cc5:4071:a29b:83ac,
mac = 90:a4:de:9c:a2:7a},NetworkInterface {name = "VirtualBox Host-Only Network"
, ipv4 = 192.168.56.1, ipv6 = fe80:0:0:0:91e2:7d75:e6f7:d90f, mac = 0a:00:27:00:
00:00},NetworkInterface {name = "Loopback Pseudo-Interface 1", ipv4 = 127.0.0.1,
ipv6 = 0:0:0:0:0:0:0:1, mac = 00:00:00:00:00:00},NetworkInterface {name = "Loca
l Area Connection* 12", ipv4 = 0.0.0.0, ipv6 = fe80:0:0:0:0:100:7f:fffe, mac = 0
0:00:00:00:00:00},NetworkInterface {name = "isatap.home", ipv4 = 64.3.66.5, ipv6
= fe80:0:0:0:0:5efe:c0a8:10c, mac = 00:00:00:00:00:00},NetworkInterface {name =
"isatap.{7F25AE4D-EDF3-491F-ADED-642C194C94D9}", ipv4 = 0.0.0.0, ipv6 = fe80:0:
0:0:0:5efe:c0a8:3801, mac = 00:00:00:00:00:00}]
那么如何提取价值:192.168.1.12?
答案 0 :(得分:3)
从文档中可以得到NetworkInterface
data NetworkInterface = NetworkInterface { name :: String
, ipv4 :: IPv4
, ipv6 :: IPv6
, mac :: MAC}
这告诉您,如果您想访问name
等,您具有相同名称的访问者功能,类型签名为name :: NetworkInterface -> String
(类似于其他人) - 因此,如果您想要提取您正在寻找类似?? :: (NetworkInterfaces -> String) -> [NetworkInterfaces] -> [String]
的网络接口列表中的名称,这是此类型签名?? :: (a -> b) -> [a] -> [b]
的特殊情况,将其放入hoogle,您会看到一个名为{{1}的函数作为第一个结果。
因此,为了收集网络名称,您只需要map
。
但是如果你想将这些函数应用于map names ns
的结果,那么这个getNetworkInterfaces
指标就不适合这种类型的签名;但是存在一个名为IO
的函数 - 我们已经看到的函数fmap
的更一般版本可以帮助我们。
map
采用一个容器(在这种情况下是fmap
和一个对容器起作用的函数,并以合理的方式将该函数应用于所述容器,(顺便说一句,提供这种功能的所有容器都是叫IO
)。
因此,为了直接从Functors
获取你的名字,你需要输入你的ghci:
getNetworkInterfaces
或使用'backtick-syntax'
Prelude> ns <- fmap (map name) getNetworkInterfaces
如果你Prelude> ns <- map name `fmap` getNetworkInterfaces
,你会得到这个非常方便的中缀运算符import Control.Applicative
,可让你将其编写为<$>
map name <$> getNetworkInterfaces
实际上是一个函数 - 它的类型签名被省略 - 是showInterface
,这意味着它需要showInterface :: NetworkInterface -> String
并生成NetworkInterface
。所以String
实际上是一个网络接口,它(通过我发布的数据声明)有4个访问函数,用于获取n
,name
,ipv4
和{{1} }。不幸的是,产生ipv6
输出的mac
函数具有类型签名putStr
,它只适用于已经stdout
的{{1}},以获得剩余的3为了工作,我们必须使用haskell的String -> IO ()
- 方法,称为name
,String
所做的其余工作是将toString()
与show
运算符拼接在一起。 (旁注:showInterface
将两个相同类型的列表拼接在一起,而String
只是++
= (++)
列表
那么String
最后会做什么 - 它与[Char]
非常类似(因此名称),但它允许发生副作用,幸运的是足够打印到stdout({{1} }})是这样的副作用。请注意,有两个函数非常相似Char
和mapM_
您可能会不时在haskell-land中看到的下划线表示丢弃/不需要的东西,在这种情况下是结果 - 其中这种情况map
会生成putStr
,mapM
只会忘记列表并生成mapM_
(说IO单位 - 您可以在C-中考虑mapM
就像语言一样,我的助记符是IO [()]
,其中包含io,但有一些东西可以隐藏它并拼写错误的顺序。)
顺便提一下,mapM_
的类型签名也被省略IO ()
,它与void
完全吻合。